File: vector.rb

package info (click to toggle)
ruby-classifier 1.3.4-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 224 kB
  • sloc: ruby: 739; makefile: 5
file content (112 lines) | stat: -rw-r--r-- 2,421 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# Author::    Ernest Ellingson
# Copyright:: Copyright (c) 2005 

# These are extensions to the std-lib 'matrix' to allow an all ruby SVD

require 'matrix'
require 'mathn'

class Array
  def sum(identity = 0, &block)
    return identity unless size > 0
  
    if block_given?
      map(&block).sum
    else
      reduce(:+)
    end
  end
end

class Vector
  def magnitude
    sumsqs = 0.0
    self.size.times do |i|
      sumsqs += self[i] ** 2.0 
    end
    Math.sqrt(sumsqs)
  end
  def normalize
    nv = []
    mag = self.magnitude
    self.size.times do |i|

      nv << (self[i] / mag)

    end
    Vector[*nv]
  end
end

class Matrix
  def Matrix.diag(s)
     Matrix.diagonal(*s)
  end
  
  alias :trans :transpose

  def SV_decomp(maxSweeps = 20)
    if self.row_size >= self.column_size
      q = self.trans * self
    else
      q = self * self.trans
    end
    
    qrot    = q.dup
    v       = Matrix.identity(q.row_size)
    azrot   = nil
    mzrot   = nil
    cnt     = 0
    s_old   = nil
    mu      = nil

    while true do
      cnt += 1
      for row in (0...qrot.row_size-1) do
        for col in (1..qrot.row_size-1) do
          next if row == col
          h = Math.atan((2 * qrot[row,col])/(qrot[row,row]-qrot[col,col]))/2.0
          hcos = Math.cos(h)
          hsin = Math.sin(h)
          mzrot = Matrix.identity(qrot.row_size)
          mzrot[row,row] = hcos
          mzrot[row,col] = -hsin
          mzrot[col,row] = hsin
          mzrot[col,col] = hcos
          qrot = mzrot.trans * qrot * mzrot
          v = v * mzrot
        end 
      end
      s_old = qrot.dup if cnt == 1
      sum_qrot = 0.0 
      if cnt > 1
        qrot.row_size.times do |r|
          sum_qrot += (qrot[r,r]-s_old[r,r]).abs if (qrot[r,r]-s_old[r,r]).abs > 0.001
        end
        s_old = qrot.dup
      end 
      break if (sum_qrot <= 0.001 and cnt > 1) or cnt >= maxSweeps
    end # of do while true
    s = []
    qrot.row_size.times do |r|
      s << Math.sqrt(qrot[r,r])
    end
    #puts "cnt = #{cnt}"
    if self.row_size >= self.column_size
      mu = self *  v * Matrix.diagonal(*s).inverse     
      return [mu, v, s]
    else
      puts v.row_size
      puts v.column_size
      puts self.row_size
      puts self.column_size
      puts s.size

      mu = (self.trans * v *  Matrix.diagonal(*s).inverse)
      return [mu, v, s]
    end
  end
  def []=(i,j,val)
    @rows[i][j] = val
  end
end