Juliaで連立方程式を解く
Juliaで連立方程式を解く
はじめに
2023年7月10日〜7月12日に九州大学ので開催された「数学と物理におけるJuliaの活用」に参加しました。7月11日の1日だけの参加(東京→博多→東京の日帰り!)だったのですが,日本でJuliaを薦めている多くの方とお会いできてとても楽しかったです。
Webサイトもありますので,これからJuliaを始める方はとても参考になると思います。
東京に帰ってきて,「何かJuliaでやりたいな。」と思っていたところ,うちの長男(大学1年生)が線形代数の問題に取り組んでいたので,その問題をjuliaで解いてみることにしました。
同じ問題でも良かったのですが,数字は少し変えました。
連立方程式を解く
次の2つの連立方程式を解くことを考えます。
1つ目の連立方程式
まず,
を定義します。
はJuliaではA₁\B₁
で求めることができます。
A₁ = [
1 2 1 -1
1 2 -1 1
2 1 1 2
1 3 2 -4
]
4×4 Matrix{Int64}:
1 2 1 -1
1 2 -1 1
2 1 1 2
1 3 2 -4
B₁ = [
1
1
1
1
]
4-element Vector{Int64}:
1
1
1
1
A₁\B₁
4-element Vector{Float64}:
-0.3333333333333328
0.6666666666666664
0.3333333333333331
0.3333333333333331
小数表示でもいいのですが,有理数の分数表示をしてみます。
A₁ = [
1 2 1 -1
1 2 -1 1
2 1 1 2
1 3 2 -4//1
]
4×4 Matrix{Rational{Int64}}:
1//1 2//1 1//1 -1//1
1//1 2//1 -1//1 1//1
2//1 1//1 1//1 2//1
1//1 3//1 2//1 -4//1
B₁ = [
1
1
1
1//1
]
4-element Vector{Rational{Int64}}:
1//1
1//1
1//1
1//1
A₁\B₁
4-element Vector{Rational{Int64}}:
-1//3
2//3
1//3
1//3
2つ目の連立方程式
同じように,
を定義します。
はA₂\B₂
で求めてみます。
A₂= [
1 2 1 -1
1 2 -1 1
2 1 1 2
1 3 2 -3
]
4×4 Matrix{Int64}:
1 2 1 -1
1 2 -1 1
2 1 1 2
1 3 2 -3
B₂= [
1
3
-3
2
]
4-element Vector{Int64}:
1
3
-3
2
A₂\B₂
4-element Vector{Float64}:
1.6000000000000005
0.19999999999999946
-2.8
-1.8000000000000003
こちらも有理数の分数表示をしてみましょう。
A₂= [
1 2 1 -1
1 2 -1 1
2 1 1 2
1 3 2 -3//1
]
4×4 Matrix{Rational{Int64}}:
1//1 2//1 1//1 -1//1
1//1 2//1 -1//1 1//1
2//1 1//1 1//1 2//1
1//1 3//1 2//1 -3//1
B₂= [
1
3
-3
2//1
]
4-element Vector{Rational{Int64}}:
1//1
3//1
-3//1
2//1
A₂\B₂
SingularException(4)
Stacktrace:
[1] checknonsingular
@ ~/.julia/juliaup/julia-1.9.2+0.aarch64.apple.darwin14/share/julia/stdlib/v1.9/LinearAlgebra/src/factorization.jl:19 [inlined]
[2] generic_lufact!(A::Matrix{Rational{Int64}}, pivot::RowMaximum; check::Bool)
......
あれ,エラーだ。どうしてだろう?(わざとらしい。。。)
ということで,ランクを調べてみます。行列のランクを調べるにはLinearAlgebra.jl
のパッケージを利用します。
行列のランクを調べ,逆行列を確認
using LinearAlgebra
rank(A₂)
3
A₂\B₂
が求まったのか不思議ですが,恐らく,解が不定で,解の1つが表示されたと思われます。
いずれにして,ちゃんと求めなくては!
rank(A₁)
4
逆行列はinv(A)
で求めます。
inv(A₁)
4×4 Matrix{Rational{Int64}}:
-9//2 5//6 4//3 2//1
5//2 -1//6 -2//3 -1//1
5//2 -5//6 -1//3 -1//1
2//1 -1//3 -1//3 -1//1
inv(A₂)
SingularException(4)
.......
行簡約階段形(Reduced row echelon form)
行簡約階段形を行います。詳細は
をみてください。RowEchelon.jl
パッケージのrref(A)
コマンドを用います。
using RowEchelon
rref(A₂)
4×4 Matrix{Rational{Int64}}:
1//1 0//1 0//1 2//1
0//1 1//1 0//1 -1//1
0//1 0//1 1//1 -1//1
0//1 0//1 0//1 0//1
ちょっと目がチカチカするのでLatexify.jl
を\パッケージを用いて,数式っぽくします。
using Latexify
rref(A₂)|>latexify
第4行に0が並び,ランクが3であることがわかります。
まず,
A₂E = hcat(A₂,Matrix(I, 4 ,4))
4×8 Matrix{Rational{Int64}}:
1//1 2//1 1//1 -1//1 1//1 0//1 0//1 0//1
1//1 2//1 -1//1 1//1 0//1 1//1 0//1 0//1
2//1 1//1 1//1 2//1 0//1 0//1 1//1 0//1
1//1 3//1 2//1 -3//1 0//1 0//1 0//1 1//1
行基本変形を用いて,行簡約階段形にします。
rref(A₂E)
4×8 Matrix{Rational{Int64}}:
1//1 0//1 0//1 2//1 0//1 1//12 7//12 -1//4
0//1 1//1 0//1 -1//1 0//1 1//4 -1//4 1//4
0//1 0//1 1//1 -1//1 0//1 -5//12 1//12 1//4
0//1 0//1 0//1 0//1 1//1 -1//6 -1//6 -1//2
を解くには
を解けばOKです。
とおきます。
Symbolics.jl
パッケージを用いて,文字を扱えるようにします。
using Symbolics
@variables x₁ x₂ x₃ x₄
X₂=[x₁
x₂
x₃
x₄]
rref(A₂)*X₂
となります。
rref(A₂E)[1:4,5:8]*B₂
4-element Vector{Rational{Int64}}:
-2//1
2//1
-1//1
0//1
となります。
第4行が共に0であるので,
eqs = [(rref(A₂)*X₂)[i]~(rref(A₂E)[1:4,5:8]*B₂)[i] for i =1:3]
var = [x₁, x₂ ,x₃]
Symbolics.solve_for(eqs,var)
3-element Vector{SymbolicUtils.BasicSymbolic{Real}}:
(-2//1) - (2//1)*x₄
(2//1) + x₄
x₄ - (1//1)
と求まりました。
まとめ
連立方程式を解くときは,まずランクを調べよう!
Discussion