# Linear Algebra
#
# by Shin-ichiro Hara
#
# Version 1.00 (2001.11.01)
require "algebra/matrix-algebra"
require "algebra/gaussian-elimination"
require "algebra/polynomial"
require "algebra/polynomial-factor"
require "algebra/algebraic-equation"
require "algebra/jordan-form"
module Algebra
module Orthogonalization
def orthogonalize
orth_basis = []
vectors.each_with_index do |b, i|
orth_basis.push b
if i > 0
orth_basis[0...i].each do |f|
orth_basis[i] -= b.inner_product(f) / f.norm2 * f
# orth_basis[i] = f.norm2*orth_basis[i] - b.inner_product(f)*f #also
end
end
end
self.class.collect_column{|j| orth_basis[j]}
end
def normalize
k = ground
orth_basis = []
vectors.each do |b|
k, n = Sqrt(k, b.norm2)
orth_basis.push Vector(k, size) ** b / n
end
Algebra.SquareMatrix(k, size).collect_column{|j| orth_basis[j]}
end
end
class MatrixAlgebra
include Orthogonalization
auto_req_init
auto_req :e_diagonalize, "algebra/elementary-divisor"
auto_req :elementary_divisor, "algebra/elementary-divisor"
end
class SquareMatrix < MatrixAlgebra
def self.symmetric(*a)
k = size*(size+1)/2
raise "the size of #{a.inspect} must be <= #{k}" if a.size > k
matrix{ |i, j|
d = (i - j).abs
a[(i < j ? i : j) + (2*size+1-d)*d/2 ] || ground.zero
}
end
EigenSystem = Struct.new("EigenSystem",
:extfield,
:roots,
:tmatrix,
:evalues,
:addelms,
:evectors,
:espaces,
:chpoly,
:facts)
def diagonalize
chp = char_polynomial(Algebra.Polynomial(ground, "t"))
facts = chp.factorize
mdf, mods, fas, roots, proots = chp.decompose(facts)
nu = Algebra.SquareMatrix(mdf, size)
espaces = {}
evalues = []
evectors = []
roots0 = []
k = 0
facts.each do |f, n|
dim = f.deg
if dim <= 0 # 0 might be occurred
next
elsif dim == 1
evs = [-f[0]/f[1]]
else
evs = roots[k, dim]#.reverse
roots0.push [f, evs]
end
k += dim
evs.each do |evalue|
ks = nu.const(evalue) - self
kb = ks.kernel_basis
espaces[evalue] = kb
kb.each do |v|
evalues.push evalue
evectors.push v
end
end
end
raise "can't Diagonalize" if evalues.size < size
ttype = Algebra.SquareMatrix(mdf, size)
r = ttype.collect_column{|i| evectors[i]}
# :extfield, :roots, :tmatrix, :evalues, :addelms, :evectors,
# :espaces, :chpoly, :facts
e = EigenSystem.new(mdf, roots0, r, evalues, proots, evectors,
espaces, chp, facts)
def e.to_ary; to_a; end
e
end
def solve_eigen_value_problem
puts "A = "; display; puts
e = diagonalize
puts "Charactoristic Poly.: #{e.chpoly} => #{e.facts}"; puts
puts "Algebraic Numbers:"
e.roots.each do |po, rs|
puts "#{rs.join(', ')} : roots of #{po} == 0"
end; puts
puts "EigenSpaces: "
e.evalues.uniq.each do |ev|
puts "W_{#{ev}} = <#{e.espaces[ev].join(', ')}>"
end; puts
puts "Trans. Matrix:"
puts "P ="
e.tmatrix.display; puts
puts "P^-1 * A * P = "; (e.tmatrix.inverse * self * e.tmatrix).display; puts
end
end
end
if __FILE__ == $0
end
syntax highlighted by Code2HTML, v. 0.9.1