Skip to content

Instantly share code, notes, and snippets.

@leandro
Created October 3, 2009 21:12
Show Gist options
  • Save leandro/200887 to your computer and use it in GitHub Desktop.
Save leandro/200887 to your computer and use it in GitHub Desktop.
require 'matrix'
module FixnumExt
def square?
sqrt = self ** (1.0/2)
(sqrt - sqrt.to_i).zero?
end
end
module MatrixDeterminant
def det2
return nil unless self.square?
return self[0,0] if self.row_size == 1
return self[0,0] * self[1,1] - self[0,1] * self[1,0] if self.row_size == 2
return self[0,0] * self[1,1] * self[2,2] + self[1,0] * self[2,1] * self[0,2] + self[2,0] * self[0,1] * self[1,2] -
self[0,2] * self[1,1] * self[2,0] - self[0,0] * self[1,2] * self[2,1] - self[0,1] * self[1,0] *
self[2,2] if self.row_size == 3
# calculating determinant for 4x4 or bigger
most_zeros_line = self.lowest_cost_line
_row = most_zeros_line > 0
line_index = _row ? most_zeros_line - 1 : most_zeros_line.abs - 1
line = (_row ? self.row(line_index) : self.column(line_index)).to_a
sum = 0
line.each_index {|k| sum += line[k].zero? ? 0 : line[k] * (_row ? self.minor2(line_index, k).det2 : self.minor2(k, line_index).det2)}
sum
end
def lowest_cost_line
rows = self.to_a.map {|e| e - [0]}
cols = self.transpose.to_a.map {|e| e - [0]}
lowest_row = rows.index(rows.inject(rows.first) {|lowest, e| lowest.size > e.size ? e : lowest})
lowest_col = cols.index(cols.inject(cols.first) {|lowest, e| lowest.size > e.size ? e : lowest})
rows[lowest_row].size <= cols[lowest_col].size ? lowest_row + 1 : - (lowest_col + 1)
end
def cofactor(modulus = nil)
return nil unless self.row_size == self.column_size && self.row_size > 1
r = []
self.row_size.times do |i|
r << (crow = [])
self.column_size.times do |j|
value = ((i + j + 2) * -1) * self.minor2(i, j).det2
value = value % modulus if modulus
crow << value
end
end
Matrix[*r]
end
def minor2(row, col)
r = []
self.row_size.times do |i|
next if i == row
r << (crow = [])
self.column_size.times do |j|
next if j == col
crow << self[i,j]
end
end
Matrix[*r]
end
end
module MatrixCoreExt
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def square_from_rows *members
return nil unless members.size.square?
msize = (members.size ** (1.0/2)).to_i
matrix = []
members.each_slice(msize) {|s| matrix << s}
Matrix[*matrix]
end
end
def % num
r = []
self.row_size.times do |i|
r << (crow = [])
self.column_size.times do |j|
crow << self[i,j] % num
end
end
Matrix[*r]
end
end
module Main
class ::Matrix
include MatrixDeterminant
include MatrixCoreExt
end
class ::Fixnum
include FixnumExt
end
end
include Main
Matrix.square_from_rows(0,6,0,0,0,0,7,0,0,5,4,5,1,2,1,6,2,1,4,2,3,2,0,2,1).det2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment