diff --git a/Rakefile b/Rakefile index cf700dd..fb35c96 100644 --- a/Rakefile +++ b/Rakefile @@ -43,7 +43,7 @@ task :test => :check_dependencies task :default => :test -require 'rake/rdoctask' +require 'rdoc/task' Rake::RDocTask.new do |rdoc| version = File.exist?('VERSION') ? File.read('VERSION') : "" diff --git a/VERSION b/VERSION index 167b000..389facc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.4 \ No newline at end of file +0.5.5 \ No newline at end of file diff --git a/lib/svd_matrix.rb b/lib/svd_matrix.rb index 2e38d22..ac37642 100644 --- a/lib/svd_matrix.rb +++ b/lib/svd_matrix.rb @@ -3,17 +3,13 @@ class SVDMatrix < Matrix public_class_method :new - + public :"[]=", :set_element, :set_component # Create a new SVD Matrix with m rows, n columns def initialize(m, n) + @row_size = m @rows = Array.new(m) @column_size = n - m.times {|i| @rows[i] = Array.new(n)} - end - - # Set the value of the cell i, j - def []=(i, j, val) - @rows[i][j] = val + m.times {|i| @rows[i] = Array.new(n) {0} } end # Set the value of a row to an array @@ -37,23 +33,37 @@ def inspect # [ 0, 0, 0, 0 ] def decompose(reduce_dimensions_to = nil) input_array = [] - @rows.each {|row| input_array += row} - u_array, w_array, v_array = SVD.decompose(input_array, row_size, column_size) - - # recompose U matrix - u = SVDMatrix.new(row_size, reduce_dimensions_to || column_size) - row_size.times {|i| u.set_row(i, u_array.slice!(0, column_size)[0...(reduce_dimensions_to || column_size)])} - - # recompose V matrix - v = SVDMatrix.new(column_size, reduce_dimensions_to || column_size) - column_size.times {|i| v.set_row(i, v_array.slice!(0, column_size)[0...(reduce_dimensions_to || column_size)])} - - # diagonalise W array as a matrix - if reduce_dimensions_to - w_array = w_array[0...reduce_dimensions_to] - end - w = Matrix.diagonal(*w_array) - + + if @row_size >= @column_size + + @rows.each {|row| input_array += row} + u_array, w_array, v_array = SVD.decompose(input_array, row_size, column_size) + + # recompose U matrix + u = SVDMatrix.new(row_size, reduce_dimensions_to || column_size) + row_size.times {|i| u.set_row(i, u_array.slice!(0, column_size)[0...(reduce_dimensions_to || column_size)])} + + # recompose V matrix + v = SVDMatrix.new(column_size, reduce_dimensions_to || column_size) + column_size.times {|i| v.set_row(i, v_array.slice!(0, column_size)[0...(reduce_dimensions_to || column_size)])} + + # diagonalise W array as a matrix + if reduce_dimensions_to + w_array = w_array[0...reduce_dimensions_to] + end + w = Matrix.diagonal(*w_array) + + else + + transpose = SVDMatrix.new( @column_size, @row_size ) + @rows = @rows.transpose + for i in 0..@column_size-1 + transpose.set_row(i, @rows[i].to_a ) + end + v , w, u = transpose.decompose( reduce_dimensions_to || @row_size ) + + end + [u, w, v] end