#----------------------------------------------------------------
# ### Determinant
#----------------------------------------------------------------
# 行列式类。用于计算、处理、表达行列式的类。
#----------------------------------------------------------------
class Determinant <
#----------------------------------------------------------------
# ## 超类
#----------------------------------------------------------------
# Object
#----------------------------------------------------------------
Object
#----------------------------------------------------------------
# ## 包含的模块
#----------------------------------------------------------------
# Comparable
#----------------------------------------------------------------
include(Comparable)
#----------------------------------------------------------------
# ## 类方法
#----------------------------------------------------------------
class << self
#----------------------------------------------------------------
# # Determinant[row1, row2, …]
#----------------------------------------------------------------
# 基本同Determinant.new。不同之处在于此方法的参数是多个长度相等的数组,
# 而Determinant.new的参数是嵌套数组。
#----------------------------------------------------------------
def [](*rows)
return new(rows)
end
#----------------------------------------------------------------
# # Determinant.new(rows)
#----------------------------------------------------------------
# 生成一个与rows内容相同的行列式。
# rows是一个嵌套数组,且rows内的数组的长度应与rows的长度相等,否则会引
# 发TypeError。
#----------------------------------------------------------------
def new(rows)
super(rows)
end
end
#----------------------------------------------------------------
# ## 方法
#----------------------------------------------------------------
#----------------------------------------------------------------
# # size
#----------------------------------------------------------------
# 返回行列式的阶数。
#----------------------------------------------------------------
def size
return rows.size
end
#----------------------------------------------------------------
# # order
#----------------------------------------------------------------
# 同size。
#----------------------------------------------------------------
def order
return size
end
#----------------------------------------------------------------
# # cofactor(x, y)
#----------------------------------------------------------------
# 返回在x、y位置的余子式。
#----------------------------------------------------------------
def cofactor(x, y)
ary = rows.clone
ary.delete_at(x)
for i in 0...(order - 1)
ary[i] = i >= x ? rows[i].clone : rows[i + 1].clone
ary[i].delete_at(y)
end
return Determinant.new(ary)
end
#----------------------------------------------------------------
# # cof(x, y)
#----------------------------------------------------------------
# 同cofactor。
#----------------------------------------------------------------
def cof(x, y)
return cofactor(x, y)
end
#----------------------------------------------------------------
# # algebraic_cofactor(x, y)
#----------------------------------------------------------------
# 返回在x、y位置的代数余子式。
#----------------------------------------------------------------
def algebraic_cofactor(x, y)
return (-1) ** (x + y) * cofactor(x, y).value
end
#----------------------------------------------------------------
# # alc(x, y)
#----------------------------------------------------------------
# 同algebraic_cofactor。
#----------------------------------------------------------------
def alc(x, y)
return algebraic_cofactor(x, y)
end
#----------------------------------------------------------------
# # at(x, y)
#----------------------------------------------------------------
# 返回在x、y位置的元素。
#----------------------------------------------------------------
def at(x, y)
return rows[x][y]
end
#----------------------------------------------------------------
# # self[x, y]
#----------------------------------------------------------------
# 同at。
#----------------------------------------------------------------
def [](x, y)
return at(x, y)
end
#----------------------------------------------------------------
# # self[x, y] = val
#----------------------------------------------------------------
# 为在x、y位置的元素赋值代入val。
# 返回val。
#----------------------------------------------------------------
def []=(x, y, val)
return rows[x][y] = val
end
#----------------------------------------------------------------
# # rows = val
#----------------------------------------------------------------
# 为rows赋值代入val。
# 返回val。
#----------------------------------------------------------------
def rows=(val)
raise(TypeError) if !val.is_a?(Array)
for i in val
raise(TypeError) if !i.is_a?(Array) or i.size != val.size
end
return @rows = val
end
#----------------------------------------------------------------
# # row(x)
#----------------------------------------------------------------
# 返回与第x行内容相同的数组。
# 请参考column。
#----------------------------------------------------------------
def row(x)
return rows[x]
end
#----------------------------------------------------------------
# # column(y)
#----------------------------------------------------------------
# 返回与第y列内容相同的数组。
# 请参考row。
#----------------------------------------------------------------
def column(y)
ary = []
for i in rows
ary += i[y].to_a
end
return ary
end
#----------------------------------------------------------------
# # change_row(x, ary)
#----------------------------------------------------------------
# 把第x行的内容代替为数组ary的内容。返回self。
# ary的元素的数量必须与行列式的阶数相等,否则会引发TypeError。
# 请参考change_column。
#----------------------------------------------------------------
def change_row(x, ary)
rows[x] = ary
return self
end
#----------------------------------------------------------------
# # change_column(y, ary)
#----------------------------------------------------------------
# 把第y列的内容代替为数组ary的内容。返回self。
# ary的元素的数量必须与行列式的阶数相等,否则会引发TypeError。
# 请参考change_row。
#----------------------------------------------------------------
def change_column(y, ary)
for i in 0...size
rows[i][y] = ary[i]
end
return self
end
#----------------------------------------------------------------
# # transpose
#----------------------------------------------------------------
# 转置变换。指把行列式逆时针旋转1/4圈。返回self。
# 行列式的性质1:行列式转置后,其值不变(请参考value)。
#----------------------------------------------------------------
def transpose
det = self
for i in 0...size
change_column(i, det.row(i))
end
return self
end
#----------------------------------------------------------------
# # exchange_row(x, x_ed)
#----------------------------------------------------------------
# 换法变换。指把第x行与第x_ed行的位置互换。返回self。
# 行列式的性质2:互换行列式的两行(列),行列式变号(请参考value)。
# 请参考exchange_column。
#----------------------------------------------------------------
def exchange_row(x, x_ed)
a = row(x)
b = row(x_ed)
change_row(x, b)
change_row(x_ed, a)
return self
end
#----------------------------------------------------------------
# # exchange_column(y, y_ed)
#----------------------------------------------------------------
# 换法变换。指把第y列与第y_ed列的位置互换。返回self。
# 请参考exchange_row。
#----------------------------------------------------------------
def exchange_column(y, y_ed)
a = column(y)
b = column(x_ed)
change_column(y, b)
change_column(y_ed, a)
return self
end
#----------------------------------------------------------------
# # multiply_row(x, num)
#----------------------------------------------------------------
# 倍法变换。指把第x行的每一个元素都乘num。返回self。
# 行列式的性质3:行列式的某一行(列)的所有元素都乘k,等同于用k乘这个行
# 列式(请参考value)。
# 请参考multiply_column。
#----------------------------------------------------------------
def multiply_row(x, num)
for i in 0...size
self[x, i] *= num
end
return self
end
#----------------------------------------------------------------
# # multiply_column(y, num)
#----------------------------------------------------------------
# 倍法变换。指把第y列的每一个元素都乘num。返回self。
# 请参考multiply_row。
#----------------------------------------------------------------
def multiply_column(y, num)
for i in 0...size
self[i, y] *= num
end
return self
end
#----------------------------------------------------------------
# # transform_row(x, x_ed, num)
#----------------------------------------------------------------
# 消法变换。指把第x行的每一个元素都加上第x_ed行的对应元素乘num的积。返
# 回self。
# 行列式的性质5:把行列式的某一行(列)的元素都乘k后加到另一行(列)的对
# 应元素上去,行列式的值不变(请参考value)。
# (行列式的性质4:如果行列式的某一行(列)的元素都是多项式,就可以把该
# 行列式拆成多个行列式的和(请参考value)。)
# 请参考transform_column。
#----------------------------------------------------------------
def transform_row(x, x_ed, num)
raise(TypeError) if x == x_ed or x >= size or x_ed >= size
for i in 0...size
self[x, i] += row(x_ed)[i] * num
end
return self
end
#----------------------------------------------------------------
# # transform_column(y, y_ed, num)
#----------------------------------------------------------------
# 消法变换。指把第x行的每一个元素都加上第x_ed行的对应元素乘num的积。返
# 回self。
# 请参考transform_row。
#----------------------------------------------------------------
def transform_column(y, y_ed, num)
raise(TypeError) if y == y_ed or y >= size or y_ed >= size
for i in 0...size
self[i, y] += y(y_ed)[i] * num
end
return self
end
#----------------------------------------------------------------
# # value(expand_calculate = false)
#----------------------------------------------------------------
# 返回行列式的值。当expand_calculate为true时计算时间较长但没有任何误
# 差,为false时计算时间较短但在阶数较大时会有细微误差。
# 若行列式中没有浮点数则返回整数,否则返回浮点数。
#----------------------------------------------------------------
def value(expand_calculate = false)
f = false
for i in 0...size
for j in 0...size
if at(i, j).is_a?(Float)
f = true
break
end
break if f == true
end
if expand_calculate
if order == 1
return at(0, 0)
else
val = 0
for i in 0...order
val += at(0, i) * algebraic_cofactor(0, i)
end
end
else
det = self.dup
for i in 0...size
j = 0
i.times do
if at(j, j) == 0
return 0.0 if f
return 0
end
det.transform_row(i, j, -(at(i, j) / at(j, j).to_f))
j += 1
end
end
val = 1
for i in 0...size
val *= det[i, i]
end
end
return val.to_i unless f
return val
end
#----------------------------------------------------------------
# # inspect
#----------------------------------------------------------------
# 返回表达行列式的字符串。
#----------------------------------------------------------------
def inspect
str = ""
for i in rows
str += i.inspect + "\n"
end
return str
end
#----------------------------------------------------------------
# # to_s
#----------------------------------------------------------------
# 同inspect。
#----------------------------------------------------------------
def to_s
return inspect
end
#----------------------------------------------------------------
# # to_a
#----------------------------------------------------------------
# 同rows。
#----------------------------------------------------------------
def to_a
return rows
end
#----------------------------------------------------------------
# # to_f
#----------------------------------------------------------------
# 同value.to_f。
#----------------------------------------------------------------
def to_f
return value.to_f
end
#----------------------------------------------------------------
# # to_i
#----------------------------------------------------------------
# 同value.to_i。
#----------------------------------------------------------------
def to_i
return value.to_i
end
#----------------------------------------------------------------
# # self <=> other
#----------------------------------------------------------------
# 对self和other进行比较。若self.value较大时返回正数,若相等时返回0,
# 若较小时返回负数。
#----------------------------------------------------------------
def <=>(other)
if other.is_a?(Determinant)
return value <=> other.value
else
return value <=> other
end
end
#----------------------------------------------------------------
# # eql?(other)
#----------------------------------------------------------------
# 若rows与other的rows用eql?比较为true则返回true,否则返回false。
#----------------------------------------------------------------
def eql?(other)
if other.is_a?(Determinant)
return rows.eql?(other.rows)
else
return false
end
end
#----------------------------------------------------------------
# ## 属性
#----------------------------------------------------------------
#----------------------------------------------------------------
# # rows
#----------------------------------------------------------------
# 返回与行列式的内容一样的嵌套数组。
# 请参考Determinant.new
#----------------------------------------------------------------
attr_accessor(:rows)
#----------------------------------------------------------------
# ## 私有方法
#----------------------------------------------------------------
#----------------------------------------------------------------
# # initialiaze(rows)
#----------------------------------------------------------------
# 行列式对象被建立之后初始化的方法,该方法的参数会全部传递给Determinant
# .new。这里定义了rows属性的初始值。
#----------------------------------------------------------------
def initialize(rows)
raise(TypeError) unless rows.is_a?(Array)
for i in rows
raise(TypeError) if !i.is_a?(Array) or i.size != rows.size
end
@rows = rows
end
#----------------------------------------------------------------
# # initialiaze_copy(det)
#----------------------------------------------------------------
# 行列式对象被复制之后初始化的方法。
# 行列式的克隆中,它的rows和rows内部的数组都是原行列式对象的rows和rows
# 内部的数组的克隆。其余信息的克隆都和一般的对象相同,即Object类内的定义。
#----------------------------------------------------------------
def initialize_copy(det)
det.rows = rows.dup
for i in 0...size
det.rows[i] = rows[i].dup
end
end
end