使う前に
SymPy.jlはJuliaで記号計算をするための拡張機能です。これを使ってREPL(Juliaの黒い画面)上で記号計算をしても良いのですが見づらいです。見やすくするために、IJuliaのJupyter NotebookやJupyter Labを立ち上げ、そこで記号計算をすると良いです。大抵はMathJaxによるきれいな数式が表示されるので見やすくなります。つまり、
using IJulia
notebook()
または、
using IJulia
jupyterlab()
を実行してNotebookを作り、その中でSymPy.jlを使うと良いです。SymPy.jlを使う前には都度、以下のコードを実行しておきます。
using SymPy
ただし、初回に限り以下のように拡張機能を追加しておく必要があります。
using Pkg
Pkg.add("IJulia")
Pkg.add("SymPy")
以降の説明のコードは全てusing SymPy
の後で実行するものとします。
変数を作る
例1:xを作る
@syms x
#上記は下記の省略(マクロを使った記法)
x = Sym("x")
#下記でも同じ結果
x = symbols("x")
補足:@syms
は以前は@vars
でしたが廃止されました。
例2:xとyを一気に作る
@syms x y
#上記は下記の省略(マクロを使った記法)
x, y = Sym("x y") #"x y"の部分は"x,y"、"x, y"、"x,y,"等でも良い
#下記でも同じ結果
x, y = symbols("x y")
#上記は下記の省略(明らかなタプルの略記)
(x, y) = symbols("x y")
#ヒント:もっと理解するにはJuliaのタプル(tuple)を調べよう
例3:ギリシャ文字や下付文字
@syms x1 α beta R_max
[x1 α beta R_max]
出力(そのままの見た目):$[x_1\ \alpha\ \beta\ R_{max}]$
つまり、@syms
で作った変数の見た目は以下のようになります。
・最後の数字は下付文字になる
・ギリシャ文字はそのままギリシャ文字になる
・ギリシャ文字の名前は対応するギリシャ文字になる
・ラテン文字(ローマ字)は斜体になる
・_に後続する部分は下付文字になる
例4:変数名と見た目を分ける、立体と斜体を指定
例3の変数R_max
の見た目は$R_{max}$でしたが、変数名をRmax
(_
抜き)として見た目を$R_{\rm{max}}$(maxは斜体ではなく立体)としたい場合は以下のように書けます。
@syms Rmax=>"R_\\rm{max}"
#上記は下記の省略
Rmax = Sym("R_\\rm{max}")
#下記でも同じ結果
Rmax = symbols("R_\\rm{max}")
ここで、\\rm{A}
はAを立体:romanにする指定です(逆にAを明示的に斜体:italicにする指定は\\it{A}
です)。もっと複雑な見た目を表現したい場合は、TeX、LaTeX、MathJaxの数式の書き方を調べていろいろ真似して書いてみると良いでしょう(注:通常のTeX等で\
と書くべき所はここでは\\
に変える必要があります)。
例5:数の分類の仮定を加えて変数を作る
数の分類の仮定(実数:real、複素数:complex、整数:integer、正の数:positive、負の数:negative等)を加えて変数を作ることもできます。
例えば、ある解決したい二次方程式の問題があって、その二次方程式についての意味のある解が実数だと分かっているとします。このような場合、解かれることになる変数を作成する時に実数の仮定を付与しておくと良いです。その変数による二次方程式を作り、これをSymPyに解かせると、SymPyは判別式に応じた適切な結果を出してくれます。つまり、判別式が負なら解なしという結果を、判別式が非負なら実数解の結果を出してくれるということです。
上記のように後々の処理によっては、数の分類の情報を付与して変数を作っておいた方が都合が良いということもあるので、この方法も覚えておきましょう。
例5-1:実数を仮定する
@syms x::real #注:realは小文字始まりであること(他の指定も同様)
#上記は下記の省略
x = symbols("x", real=true) #注:symbolsをSymに変えるとエラー
補足:@syms x::real
は以前は@syms x real=true
でしたが廃止されました。
例5-2:複素数を仮定する
@syms x::complex
#上記は下記の省略
x = symbols("x", complex=true)
例5-3:正[負][非正][非負]を仮定する
下記は正(positive)の場合です。負、非正、非負を仮定した場合は、positiveをそれぞれ、negative、nonpositive、nonnegativeに置き換えましょう。
@syms x::(real, positive) #複数の仮定を付与する場合は丸括弧とカンマが使える
#上記は下記の省略
x = symbols("x", real=true, positive=true)
#下記でも同じ結果
@syms x::positive #positiveは実数で正のことなのでrealは省略可
#上記は下記の省略
x = symbols("x", positive=true)
補足:@syms x::(real, positive)
は以前は@syms x real=true positive=true
でしたが廃止されました。
例5-4:仮定の詳細を確認する
例5-3で作った変数x
の仮定の詳細は、次のコードで確認できます。
x.assumptions0
出力:
\begin{equation*}\begin{cases}\mathtt{\text{extended_nonnegative}} & \text{=>} &\text{True}\\\mathtt{\text{imaginary}} & \text{=>} &\text{False}\\\mathtt{\text{negative}} & \text{=>} &\text{False}\\\mathtt{\text{extended_nonzero}} & \text{=>} &\text{True}\\\mathtt{\text{extended_nonpositive}} & \text{=>} &\text{False}\\\mathtt{\text{nonzero}} & \text{=>} &\text{True}\\\mathtt{\text{extended_real}} & \text{=>} &\text{True}\\\mathtt{\text{complex}} & \text{=>} &\text{True}\\\mathtt{\text{extended_positive}} & \text{=>} &\text{True}\\\mathtt{\text{hermitian}} & \text{=>} &\text{True}\\\mathtt{\text{finite}} & \text{=>} &\text{True}\\\mathtt{\text{extended_negative}} & \text{=>} &\text{False}\\\mathtt{\text{zero}} & \text{=>} &\text{False}\\\mathtt{\text{real}} & \text{=>} &\text{True}\\\mathtt{\text{infinite}} & \text{=>} &\text{False}\\\mathtt{\text{nonnegative}} & \text{=>} &\text{True}\\\mathtt{\text{positive}} & \text{=>} &\text{True}\\\mathtt{\text{commutative}} & \text{=>} &\text{True}\\\mathtt{\text{nonpositive}} & \text{=>} &\text{False}\\\end{cases}\end{equation*}
また、例えばx.is_negative
のようなx.is_何らかの仮定
で、x
が何らかの仮定
となっているかを確認できます。何らかの仮定
がx.assumptions0
の中にある仮定ならば真偽が返され、ない仮定ならばNone
が返されます。
例5-5:その他の仮定
他にもいろいろな仮定を変数に付与できます。詳しくは、例えば、下記サイト中のassumptionsの項に記載の指定が使えます。
大小関係(等式と不等式)を作る
x
とa
を使って説明します。ということで、
@syms x a
を実行した状態として以降の例を見てください。
例1:xがa未満(x<a)
ineq = x ≪ a #≪は\llを入力してタブを押すと出る文字
#上記は下記の省略
ineq = Lt(x, 0) #less thanに由来
例2:xがa以下(x≦a)
ineq = x ≦ a #≦は\leqqを入力してタブを押すと出る文字
#上記は下記の省略
ineq = Le(x, a) #less than or equal toに由来
例3:xがa丁度(x=a)
eq = x ~ a #注:~が等号の代わりだ
#上記は下記の代わりの構文
eq = x ⩵ a #注:⩵は\Equalを入力してタブを押すと出る文字
#上記は下記の省略
eq = Eq(x, a)
例4:xがa以上(x≧a)
ineq = x ≧ a #≧は\geqqを入力してタブを押すと出る文字
#上記は下記の省略
ineq = Ge(x, a) #grater than or equal toに由来
例5:xが0超(x>a)
ineq = x ≫ a #≫は\ggを入力してタブを押すと出る文字
#上記は下記の省略
ineq = Gt(x, 0) #grater thanに由来
余談:未満の対義語を調べたら面白い記事https://kijiken.blog/words/「以上」「以下」「未満」「?」を見つけました。
方程式を作る
上記「大小関係(等式と不等式)を作る」の例3と同じやり方で作れます。
@syms x a b c
eq = a*x^2 + b*x ~ -c #注:~が等号の代わりだ
#上記は下記の代わりの構文
eq = a*x^2 + b*x ⩵ -c #注:⩵は\Equalを入力してタブを押すと出る文字
#上記は下記の省略
eq = Eq(a*x^2 + b*x , -c)
出力:$a x^{2} + b x = - c$
方程式を解く
@syms x a b c
eq = a*x^2 + b*x ⩵ -c
solve(eq, x) #方程式eqをxについて解く
出力:
\left[\begin{smallmatrix}\frac{- b - \sqrt{- 4 a c + b^{2}}}{2 a}\\\frac{- b + \sqrt{- 4 a c + b^{2}}}{2 a}\end{smallmatrix}\right]
上記は以下に代えても同じです。
@syms x a b c
eq = a*x^2 + b*x + c
solve(eq, x)
つまり、solve
に渡すのは、~
や⩵
で作られる方程式ではなく、方程式の片方の辺(左辺でも右辺でも)を他方の辺に全て移項したらできる空っぽでない方の辺でも良いということです。
方程式の左辺、右辺を取得する
@syms x
eq = x^2 + 10 ⩵ x
#eqの左辺を取得(直後の4行は全て同じ結果)
left_hand_side = lhs(eq)
left_hand_side = eq |> lhs
left_hand_side = eq.lhs()
left_hand_side = eq.lhs
#eqの右辺を取得(直後の4行は全て同じ結果)
right_hand_side = rhs(eq)
right_hand_side = eq |> rhs
right_hand_side = eq.rhs()
right_hand_side = eq.rhs
連立方程式を解く
@syms x y
eq1 = 3*x + 2*y ⩵ 11
eq2 = 2*x - 2*y ⩵ 4
sol = solve((eq1, eq2), (x, y)) #注:連立方程式と解きたい変数はタプルで与える
出力:
\begin{equation*}\begin{cases}x & \text{=>} &3\\y & \text{=>} &1\\\end{cases}\end{equation*}
この解をそれぞれx_sol
とy_sol
に格納したければ
x_sol = sol[x]
y_sol = sol[y]
#ヒント:もっと理解するにはJuliaの辞書(dictionary)を調べよう
とします。もしくは、次のようにsolve
を使う段階で一気に格納することもできます。
x_sol, y_sol = solve((eq1, eq2), (x, y)) |> λ->(λ[x], λ[y]) #λは適当な文字列で可
#上記は下記の省略(明らかなタプルの略記)
(x_sol, y_sol) = solve((eq1, eq2), (x, y)) |> λ->(λ[x], λ[y])
#ヒント:もっと理解するにはJuliaのパイプ演算子(pipe operator)|>と無名関数(anonymous function)->を調べよう
微分する
@syms x
y = sin(x) + x^3 + x^2 + x + 1
yd = diff(y, x) #yをxで微分する
#上記は下記の省略
yd = diff(y, x=>1) #yをxで1階微分する
出力:$3 x^{2} + 2 x + \cos{\left(x \right)} + 1$
n
階微分したい場合diff(y, x=>n)
とすれば良いということです。
積分する
@syms x
y = sin(x) + x
integrate(y, x) #yをxで積分する
出力:$\frac{x^{2}}{2} - \cos{\left(x \right)}$
注:積分定数は付きません。
定積分する
@syms x
y = sin(x) + x
integrate(y, x=>(0, PI)) #yをxの0からπまでの範囲で積分する
出力:$2 + \frac{\pi^{2}}{2}$
注:円周率にはSymPyが提供するPI
とJuliaが提供するpi
(π
でも全く同じ)があります。両者には違いがあります。前者PI
を使えば、記号パイのままどこまでも記号計算されます。一方、後者pi
(またはπ
)を使うと、一部の例外を除いて基本的に数値に変換されます。
級数展開する
例1:好きな次数まで展開
@syms a0 a1 a2 a3
@syms Δx::nonnegative
f = a0 + a1*Δx + a2*Δx^2 + a3*Δx^3 + sin(Δx) + cos(Δx)
f_series = series(f, Δx, 0, 5) #fをΔxの0まわりにビッグオーの次数が5次となるようにテイラー展開(Δxの4次までの展開)
#下記でも同じ結果
f_series = f |> x->series(x, Δx, 0, 5)
#下記でも同じ結果
f_series = f.series(Δx, 0, 5) #簡単だけれどJuliaらしくない書き方かも
出力:$1 + Δx \left(a_{1} + 1\right) + Δx^{2} \left(a_{2} - \frac{1}{2}\right) + Δx^{3} \left(a_{3} - \frac{1}{6}\right) + \frac{Δx^{4}}{24} + a_{0} + O\left(Δx^{5}\right)$
例2:ビッグオーは不要として展開
前コードのf_series
以降を次のように変えれば良いです(末尾に.removeO()
を加えるだけ)。
f_series = series(f, Δx, 0, 5).removeO()
#下記でも同じ結果
f_series = f |> x->series(x, Δx, 0, 5).removeO()
#下記でも同じ結果
f_series = f.series(Δx, 0, 5).removeO()
#注:下記はエラー(removeOという関数は存在しない)
f_series = f |> x->series(x, Δx, 0, 5) |> removeO
出力:$a_{0} + \frac{Δx^{4}}{24} + Δx^{3} \left(a_{3} - \frac{1}{6}\right) + Δx^{2} \left(a_{2} - \frac{1}{2}\right) + Δx \left(a_{1} + 1\right) + 1$
極限をとる
例1:無限大の極限
@syms Δx a b
c = a/(1/Δx + b)
limit(c, Δx=>oo) #cについてΔxを∞に限りなく近づける操作を行う
出力:$\frac{a}{b}$
注:無限大にはSymPyが提供するoo
とJuliaが提供するInf
があります。oo
とInf
で挙動が変わることはないと思いますが、念のため、oo
だけを使用しました。
例2:どちらから近付くのかを指定した極限
@syms x
limit(tan(x), x=>PI/2, dir="+") #"+"だと正から負に近づける指定("-"だとその逆)
出力:$-\infty$
注:PI
をpi
(π
でも同じ)に変えると数値解になってしまいます。
代入する
@syms x y a b c
y_ = 3*a*x + 3*b
z = c*y
z_ = z(y=>y_) #zのyをy_に代えたものをz_に格納する
#上記は下記の略記
z_ = subs(z, y=>y_)
#下記でも同じ結果
z_ = z |> subs(y=>y_)
#上記は下記の省略
z_ = z |> λ->subs(λ, y=>y_)
#ヒント:y=>y_のようなペアをカンマで区切って複数書けば一度にいくつも代入可
出力:$c \left(3 a x + 3 b\right)$
展開する
続きのコードとして説明します。
z_exp = expand(z_)
#下記でも同じ結果
z_exp = z_ |> expand
#上記は下記の省略
z_exp = z_ |> λ->expand(λ)
#下記でも同じ結果
z_exp = z_.expand() #簡単だけれどJuliaらしくない書き方かも
出力:$3 a c x + 3 b c$
括る
続きのコードとして説明します。
z_fac = factor(z_exp, c) #z_expがcで括れるなら括る
#下記でも同じ結果
z_fac = z_exp |> λ->factor(λ, c)
#下記でも同じ結果
z_fac = z_exp.factor(c) #簡単だけれどJuliaらしくない書き方かも
出力:$c \left(3 a x + 3 b\right)$
簡略化する(いい感じに簡単な形にする)
続きコードの続きとして説明します。
z_sim = simplify(z_exp)
#下記でも同じ結果
z_sim = z_exp |> simplify
#上記は下記の省略
z_sim = z_exp |> λ->simplify(λ)
#下記でも同じ結果
z_sim = z_exp.simplify() #簡単だけれどJuliaらしくない書き方かも
出力:$3 c \left(a x + b\right)$
消せるものは消す
続きのコードとして説明します。例えば、次の結果は明らかに0ですが、二つの式を減算記号でくっつけただけです。
z_sim - z_fac
出力:$3 c \left(a x + b\right) - c \left(3 a x + 3 b\right)$
これをちゃんと0に整理する場合にも次のようにsimplify
を使います。
simplify(z_sim - z_fac)
#下記でも同じ結果
z_sim - z_fac |> simplify
#下記でも同じ結果
(z_sim - z_fac).simplify() #簡単だけれどJuliaらしくない書き方かも
出力:$0$
上記の出力はsimplify
ではなくexpand
、factor
を使っても得られます。困ったらとりあえずこれらを使ってみましょう。
因数分解する
先にfactor
は括りたい時に使えることを説明しましたが、factor
の本質的な挙動は因数分解です。
@syms x
y = x/(x + 1) + 2/(x*(x + 1))
出力:$\frac{x}{x + 1} + \frac{2}{x \left(x + 1\right)}$
上記のy
を因数分解するには、次のようにします。
factor(y)
#下記でも同じ結果
factor(y, x)
出力:$\frac{x^{2} + 2}{x \left(x + 1\right)}$
部分分数分解する
上記のy
を部分分数分解するには、次のようにします。
apart(y)
#下記でも同じ結果
apart(y, x)
出力:$1 - \frac{3}{x + 1} + \frac{2}{x}$
通分して一つの分数にする
上記のy
を通分された分数にするには次のようにします。ただし、分母と分子は展開された形となります(因数分解されないということ)。
cancel(y)
出力:$\frac{x^{2} + 2}{x^{2} + x}$
分数の分母と分子を取得する
@syms a b c d
fract = (a + b)/(c + d) #分数
#分母を取得
denom = denominator(fract)
#下記でも同じ結果
denom = fract |> denominator
#分子を取得
numer = numerator(fract)
#下記でも同じ結果
numer = fract |> numerator
先程の二次方程式を行列で解く
A = Sym[3 2
2 -2]
b = Sym[11
4]
c = A\b #解のベクトル
#下記でも同じ結果
c = inv(A)*b #inv(A)はAの逆行列の計算
#もしSymをなくすとJuliaの標準の行列やベクトルとなり、cは数値解となる
#ただし、行列やベクトル中に@syms等で作った変数が一つでもあればSymは必要ない
出力:
\left[\begin{smallmatrix}3\\1\end{smallmatrix}\right]
先程と同様にx_sol
とy_sol
に格納するには次のようにします。
x_sol = c[1] #ベクトルcの1番目の成分を格納
y_sol = c[2] #ベクトルcの2番目の成分を格納
#下記でも同じ結果
x_sol, y_sol = c #ベクトルcの各成分を順々にタプルに格納
#上記は下記の省略(明らかなタプルの略記)
(x_sol, y_sol) = c
行列のエルミート転置と通常の転置
Juliaでは行列についての以下の2種類の転置をとる操作が提供されています。これはSymPyの機能で作った行列にも適用できます。
行列X
のエルミート転置:X'
行列X
の転置:transpose(X)
複素数の行列にこの2種類の転置を適用する例を以降に示します。
注:エルミート転置について、念のため説明しておきます(名前は仰々しいですが、以降の例を先に見てもらえば単純なことだと分かるかと思います)。エルミート転置とは、「転置をとる→複素共役をとる」の操作(これは「複素共役をとる→転置をとる」の操作でも同じ)でできる行列のことです。そのため、エルミート転置は共役転置等とも呼ばれます(「共役」の「役」の字は、元来「軛」(くびき)でしたが、常用漢字外ということで、ただ音が同じ「役」に書き換えられました。「共役」の字面からは特段の意味を察することはできません)。また、実数の複素共役をとる操作では元の実数が得られるだけなので、実数のエルミート転置はただの転置です。
操作1:複素数の行列を作る
a1, a2, b1, b2, c1, c2, d1, d2 = symbols("a1 a2 b1 b2 c1 c2 c3 c4", real=true)
X = [a1 + im*a2 b1 + im*b2
c1 + im*c2 d1 + im*d2]
出力:
\left[\begin{smallmatrix}a_{1} + i a_{2} & b_{1} + i b_{2}\\c_{1} + i c_{2} & c_{3} + i c_{4}\end{smallmatrix}\right]
操作2:エルミート転置をとる
X'
出力:
\left[\begin{smallmatrix}a_{1} - i a_{2} & c_{1} - i c_{2}\\b_{1} - i b_{2} & c_{3} - i c_{4}\end{smallmatrix}\right]
操作3:通常の転置をとる
transpose(X)
出力:
\left[\begin{smallmatrix}a_{1} + i a_{2} & c_{1} + i c_{2}\\b_{1} + i b_{2} & c_{3} + i c_{4}\end{smallmatrix}\right]
未知関数を作る、微分方程式を解く
例としてhttps://www.jsme.or.jp/kaisi/1210-32/の式(8)の微分方程式を解いて境界条件を適用して式(10)を求めるまでの流れを以下に示します。
#微分方程式を作る
@syms w() x EI Coef M0 q l #@syms w()で未知関数wが作れる
eq = EI*diff(w(x), x=>2) ~ 1//2*q*x^2 + (M0/l - 1//2*q*l)*x - M0
#ヒント:もっと理解するには次を実行してみよう:@macroexpand @syms w()
出力:$EI \frac{d^{2}}{d x^{2}} w{\left(x \right)} = - M_{0} + \frac{q x^{2}}{2} + x \left(\frac{M_{0}}{l} - \frac{l q}{2}\right)$
#微分方程式を解く
w_sol = dsolve(eq, w(x)) |> simplify #eqをw(x)について解いて簡略化する
出力:$w{\left(x \right)} = \frac{24 EI l \left(C_{1} + C_{2} x\right) + l x^{2} \left(- 12 M_{0} + q x^{2}\right) + 2 x^{3} \left(2 M_{0} - l^{2} q\right)}{24 EI l}$
#境界条件を適用して積分定数C1を解く
@syms C1 #これは何で必要?:ないとw_sol中のC1に言及できないから
C1_ = solve(0 ~ w_sol.rhs(x=>0), C1)[1] #[1]は何で必要?:解が1つであっても解がベクトルで作られるのでその第1成分を取得してスカラーにするため
出力:$0$
#境界条件を適用して積分定数C2を解く
@syms C2
C2_ = solve(0 ~ diff(w_sol.rhs, x)(x=>0), C2)[1]
出力:$0$
#解かれた積分定数を適用したw(x)を作る
w_ = w_sol(C1=>C1_, C2=>C2_)
出力:$w{\left(x \right)} = \frac{l x^{2} \left(- 12 M_{0} + q x^{2}\right) + 2 x^{3} \left(2 M_{0} - l^{2} q\right)}{24 EI l}$
#M0を求める
M0_ = solve(0 ~ w_.rhs(x=>l), M0)[1]
出力:$- \frac{l^{2} q}{8}$
区分的に(場合分けで)定義する
例えば、ランプ関数(https://ja.wikipedia.org/wiki/ランプ関数)は場合分けで次のように表せます。
@syms x::real
f = sympy.Piecewise((x, x ≧ 0), (0, x ≪ 0)) #最後の条件式x ≪ 0はtrueとしても良い
#ヒント:fは、subsで代入、diffで微分、integrateで積分する等の対象となりうる
出力:
\begin{cases} x & \text{for}\: x \geq 0 \\0 & \text{otherwise} \end{cases}
これに対して操作を加えると次のようになります。
@syms a
g = f + a
出力:
a + \begin{cases} x & \text{for}\: x \geq 0 \\0 & \text{otherwise} \end{cases}
全てを場合分けの波括弧の中に入れたい場合は次のようにします。
g_fold = sympy.piecewise_fold(g)
出力:
\begin{cases} a + x & \text{for}\: x \geq 0 \\a & \text{otherwise} \end{cases}
otherwiseがあることで推測がつきますが、SymPyでの通常の場合分けはif-elseif-else形式で書かれます。相互的に排他的な条件式で書かせることもでき、それは次のようにすれば行えます。
g_exclusive = sympy.piecewise_exclusive(g_fold)
出力:
\begin{cases} a + x & \text{for}\: x \geq 0 \\a & \text{for}\: x < 0 \end{cases}
区分的な表現に書き換える
不連続な関数は場合分けで表すことができます。例えば、max(x, 0)
を場合分けで表現させるには次のようにします。
@syms x
max(x, 0).rewrite("Piecewise")
出力:
\begin{cases} 0 & \text{for}\: x \leq 0 \\x & \text{otherwise} \end{cases}
好きな関数を使った形に書き換る
どんな書き換えができるのかは、とにかくコードと出力を見ていただければ理解が早いかと思います。
@syms x
#直後の3行は全て同じ結果
tan(x).rewrite("sin")
tan(x).rewrite(sin)
tan(x).rewrite(sin(x))
出力:$\frac{2 \sin^{2}{\left(x \right)}}{\sin{\left(2 x \right)}}$
tan(x)
をsin
関数を使った等価な表現に書き換えたということです。他にもいろいろな書き換えができそうです(いろいろ試してみると面白そうです)。
〈蛇足〉Julia自体のヒント(Julia自体をよく知らない人向け)
行頭に?
と打ち、続けざまに調べたいコードを打つと、Juliaがいろいろ教えてくれます。知っておきたいJuliaでの調べ方:https://qiita.com/I_ppp/items/9b660fe123bd5c5af174がとても勉強になります。
Juliaのための他の記号計算
拡張機能SymPy.jlは内部的にPythonで処理するもので、逆行列の記号計算等で速度がちょっと遅いと感じることがありました。現在は、他に純粋にJulia上で処理する類似の拡張機能Symbolics.jlというものが開発されており、先日、試用した感じだと、できないことがいろいろあって完成度がまだあまり高くはないと感じました。しかし、将来的にはこちらの方が高速に動作するJuliaのための良い記号計算の機能となるかも知れないので、ちょくちょく情報を収集していきたいです。