Skip to content

Instantly share code, notes, and snippets.

@komasaru
Created February 4, 2020 04:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komasaru/50784d31fe9b239b5d3813360fad6637 to your computer and use it in GitHub Desktop.
Save komasaru/50784d31fe9b239b5d3813360fad6637 to your computer and use it in GitHub Desktop.
Ruby script to calculate a determinant by cofactor expansion.
#! /usr/local/bin/ruby
#**************************************************************
# Ruby script to calculate a determinant by cofactor expansion.
#**************************************************************
#
class TestDeterminant
#MTX = [
# [1]
#]
#MTX = [
# [1, 2],
# [3, 4],
#]
#MTX = [
# [1, 4, 7],
# [8, 5, 2],
# [3, 9, 6]
#]
#MTX = [
# [1, 3, 5, 7],
# [4, 2, 8, 6],
# [9, 3, 7, 5],
# [4, 0, 6, 8]
#]
MTX = [
[1, 3, 5, 7, 9],
[4, 2, 8, 6, 0],
[9, 3, 7, 5, 1],
[4, 0, 6, 8, 2],
[3, 6, 9, 2, 5]
]
def exec
puts "Matrix A ="
MTX.each { |row| p row }
puts "det(A) = #{MTX.det}"
rescue => e
$stderr.puts "[#{e.class}] #{e.message}"
e.backtrace.each { |tr| $stderr.puts "\t#{trace}" }
exit 1
end
end
class Array
# 行列式の計算
# * 当メソッドは再帰的に呼ばれる
def det
# 以下の場合は例外スロー
# - 自身配列が Array クラスでない
# - 自身配列が空
# - 自身配列が正方行列でない
raise "Self is not a Array class!" unless self.class == Array
raise "Self array is nil!" if self.size == 0
raise "Self array is not a square matrix!" unless self.size == self[0].size
m = self
n = m.size
# 3行3列以下の行列の場合、
# => Sarrus による計算
case n
when 1; return m[0][0]
when 2; return m[0][0] * m[1][1] \
- m[0][1] * m[1][0]
when 3; return m[0][0] * m[1][1] * m[2][2] \
+ m[0][1] * m[1][2] * m[2][0] \
+ m[0][2] * m[1][0] * m[2][1] \
- m[0][0] * m[1][2] * m[2][1] \
- m[0][1] * m[1][0] * m[2][2] \
- m[0][2] * m[1][1] * m[2][0]
end
# 4行4列以上の行列の場合、
# => 第1行についての余因子展開(ラプラス展開)による計算
return n.times.map { |j| m[0][j] * cofactor(m, 0, j) }.sum
end
private
# 余因子(正方行列 A の (i, j) に対する)
# [方法-1] 1行ずつチェックしながら生成する方法
# [方法-2] 引数で与えた行列(配列)を一旦いわゆる「深いコピー」で
# 複製してから、 i 行と j 列を削除する方法
#
# @param m: 行列配列
# @param i: 行インデックス
# @param j: 列インデックス
# @return m2: 余因子
def cofactor(m, i, j)
# ====[ 方法-1 ]==>
#m2 = []
#n = m.size
#n.times do |k|
# next if k == i
# row = []
# n.times do |l|
# next if l == j
# row << m[k][l]
# end
# m2 << row
#end
# <===[ 方法-1 ]===
# ====[ 方法-2 ]==>
m2 = Marshal.load(Marshal.dump(m))
m2.delete_at(i)
m2 = m2.transpose
m2.delete_at(j)
m2 = m2.transpose
# <===[ 方法-2 ]===
return (-1)**(i+j) * m2.det
rescue => e
raise
end
end
TestDeterminant.new.exec if __FILE__ == $0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment