Class: Mat
- Inherits:
-
Object
- Object
- Mat
- Includes:
- Enumerable
- Defined in:
- lib/kmat.rb,
lib/kmat/misc.rb,
lib/kmat/arith.rb,
lib/kmat/linalg.rb,
lib/kmat/random.rb,
lib/kmat/logical.rb,
lib/kmat/version.rb,
lib/kmat/accessor.rb,
lib/kmat/statistics.rb
Defined Under Namespace
Modules: MatrixProductOperator Classes: InternalError, MismatchedDimensionError, NotImplementedYetError, SharingError, UncomputableMatrixError, ValueTypeError
Constant Summary collapse
- VERSION =
"0.1.0"
Class Method Summary collapse
-
.blocks(args) ⇒ Object
for example, Mat.blocks([a, b], [c, d]) returns a single matrix of [a, b; c, d].
- .hilb(n, type = :float) ⇒ Object
- .hstack(*mats) ⇒ Object
- .load(file) ⇒ Object
- .max(*args) ⇒ Object (also: maximum)
- .min(*args) ⇒ Object (also: minimum)
- .rand(m = 1, n = 1, random: $MatRandom) ⇒ Object
- .rand_orth(n, random: $MatRandom) ⇒ Object
- .randn(m = 1, n = 1, random: $MatRandom) ⇒ Object
- .vstack(*mats) ⇒ Object
Instance Method Summary collapse
- #*(other) ⇒ Object
- #**(other) ⇒ Object
- #/(other) ⇒ Object
- #<(other) ⇒ Object
- #<=(other) ⇒ Object
- #==(other) ⇒ Object
- #===(other) ⇒ Object
- #>(other) ⇒ Object
- #>=(other) ⇒ Object
- #[](*idx) ⇒ Object
- #add(other) ⇒ Object (also: #+)
- #add_times(other, alpha) ⇒ Object
- #all?(*args) ⇒ Boolean
- #any?(*args) ⇒ Boolean
-
#broadcast(other, vt = nil) ⇒ Object
extend ‘other’ to fit the shape of self this is similar to Python’s numpy broadcasting.
-
#coerce(other) ⇒ Object
to define Numeric * Mat as Mat#scalar(Numeric) remaining Mat * Mat is undefined, this returns non‐standard value.
- #diag(k = 0) ⇒ Object
-
#distance(other) ⇒ Object
distance (Frobenius norm of the difference).
- #e_div(other) ⇒ Object
- #e_mul(other) ⇒ Object
- #eigen_values ⇒ Object
- #eq(other) ⇒ Object
- #evd ⇒ Object
-
#flip(dim = :both) ⇒ Object
flip row, column or both axis ‘dim’ Symbol specifies fliping axis (:row, :col, :both, :none are available).
- #ge(other) ⇒ Object
- #geo_mean(arg = :all) ⇒ Object
- #geo_normalize(arg = :all) ⇒ Object
- #geo_normalize!(arg = :all) ⇒ Object
- #gt(other) ⇒ Object
- #hypot(other) ⇒ Object
-
#iprod(*args, inverse: false) ⇒ Object
(also: #inner_product)
inner product let x and y are column vectors and M is a square matrix the following is available (1) x.iprod => x’*x (2) x.iprod(y) => x’*y (3) M.iprod(x) => x’*M*x (4) M.iprod(x, y) => x’*M*y if ‘inverse’ is true, M is replaced by its Moore–Penrose inverse in case (1) or (2), ‘inverse’ is ignored if x or y is row vector, take transpose automatically.
- #le(other) ⇒ Object
- #least_squares(b, tor: nil, weight: nil, transpose: false) ⇒ Object (also: #ls)
- #least_squares!(a, b, tor: nil, weight: nil, transpose: false) ⇒ Object (also: #ls!)
- #ls_conj(b, tor: Float::EPSILON) ⇒ Object
- #ls_conj!(a, b, tor: Float::EPSILON) ⇒ Object
- #lt(other) ⇒ Object
- #maximum(other) ⇒ Object
- #mean(arg = :all) ⇒ Object
- #minimum(other) ⇒ Object
-
#norm(type = :two, elementwise: false) ⇒ Object
matrix norm ‘type’ Symbol or Integer specifies norm definition if ‘elementwise’ is true, return induced norm if ‘elementwise’ is false, return elementwise norm if ‘type’ is :fro, return Frobenius norm.
- #normalize ⇒ Object
- #normalize! ⇒ Object
- #over(other) ⇒ Object
- #over!(a, b) ⇒ Object
- #pinv ⇒ Object
- #pow(other) ⇒ Object
- #rand(arg = nil, random: $MatRandom) ⇒ Object
- #rand_orth(random: $MatRandom) ⇒ Object
- #randn(random: $MatRandom) ⇒ Object
- #rcond(type = :two) ⇒ Object
-
#replace_rep(src) ⇒ Object
replace self by repeated ‘src’ self will be left-top of infinitly repeated ‘src’.
-
#repmat(row_repeat, col_repeat) ⇒ Object
for example, A.repmat(2, 3) returns [A, A, A: A, A, A].
- #rpow(other) ⇒ Object
- #save(file) ⇒ Object
- #scalar(alpha) ⇒ Object
- #squared_distance(other) ⇒ Object
- #std(arg = :all, ddof: 0) ⇒ Object (also: #stddev, #standard_deviation)
- #sub(other) ⇒ Object (also: #-)
- #sum(arg = :all) ⇒ Object
- #temp ⇒ Object
- #under(other) ⇒ Object
- #under!(a, b) ⇒ Object
- #var(arg = :all, ddof: 0) ⇒ Object (also: #variance)
- #wls(b, w) ⇒ Object
-
#wls!(a, b, w) ⇒ Object
weighted least squares weight ‘w’ is a vector consists of standard deviations of errors a; (m, n)-matrix b: m-vector x: n-vector.
Methods included from Enumerable
Class Method Details
.blocks(args) ⇒ Object
for example, Mat.blocks([a, b], [c, d]) returns a single matrix of [a, b; c, d]
121 122 123 124 125 |
# File 'lib/kmat/accessor.rb', line 121 def blocks(args) vstack(*(args.map do |row| hstack(*row) end)) end |
.hilb(n, type = :float) ⇒ Object
2 3 4 5 6 |
# File 'lib/kmat/misc.rb', line 2 def hilb(n, type=:float) self.new(n, n, type) do |i, j| 1.quo(i+j+1) end end |
.hstack(*mats) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/kmat/accessor.rb', line 146 def hstack(*mats) m, n = mats[0].shape 1.upto(mats.size-1) do |i| mat = mats[i] raise MismatchedDimensionError, 'row-sizes must be the same' if mat.row_size != m n += mat.col_size end ret = Mat.new(m, n, mats[0].vtype) k = 0 m = Mat.irange(m) mats.each do |mat| ret[m, Mat.new(mat.col_size, 1, :int) do |i, j| i+k end] = mat k += mat.col_size end ret end |
.load(file) ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/kmat/misc.rb', line 7 def load(file) case file when String ret = nil File.open(file) do |f| ret = Marshal.load(f) end ret when IO Marshal.load(file) else raise ArgumentError, 'the argument must be a filepath or an IO object' end end |
.max(*args) ⇒ Object Also known as: maximum
159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/kmat/arith.rb', line 159 def max(*args) case args.size when 0 nil when 1 args[0] else ret = args[0].dup 1.upto(args.size-1) { |i| ret.maximum!(args[i]) } ret end end |
.min(*args) ⇒ Object Also known as: minimum
174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/kmat/arith.rb', line 174 def min(*args) case args.size when 0 nil when 1 args[0] else ret = args[0].dup 1.upto(args.size-1) { |i| ret.minimum!(args[i]) } ret end end |
.rand(m = 1, n = 1, random: $MatRandom) ⇒ Object
100 101 102 |
# File 'lib/kmat/random.rb', line 100 def rand(m=1, n=1, random: $MatRandom) _rand0(m, n, random) end |
.rand_orth(n, random: $MatRandom) ⇒ Object
69 70 71 |
# File 'lib/kmat/linalg.rb', line 69 def self.rand_orth(n, random: $MatRandom) Mat.new(n, n, :float).rand_orth(random: random) end |
.randn(m = 1, n = 1, random: $MatRandom) ⇒ Object
103 104 105 |
# File 'lib/kmat/random.rb', line 103 def randn(m=1, n=1, random: $MatRandom) _randn0(m, n, random) end |
.vstack(*mats) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/kmat/accessor.rb', line 127 def vstack(*mats) m, n = mats[0].shape 1.upto(mats.size-1) do |i| mat = mats[i] raise MismatchedDimensionError, 'column-sizes must be the same' if mat.col_size != n m += mat.row_size end ret = Mat.new(m, n, mats[0].vtype) k = 0; n = Mat.irange(n) mats.each do |mat| ret[Mat.new(mat.row_size, 1, :int) do |i, j| i+k end, n] = mat k += mat.row_size end ret end |
Instance Method Details
#*(other) ⇒ Object
59 60 61 62 63 64 65 |
# File 'lib/kmat/arith.rb', line 59 def *(other) if other.kind_of?(Mat) raise ArgumentError, "Mat#* is available only for scalar multiplication. To use Mat#*(Mat) for matrix product, call `using Mat::MatrixProductOperator'" else self.dup.s_mul!(other) end end |
#**(other) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/kmat/arith.rb', line 111 def **(other) case other when Integer ret, temp = self.dup, self.dup ret.eye if 0 <= other a = self.dup else a = self.inv other = -other end loop do if other % 2 == 1 temp.mprod!(ret, a) temp, ret = ret, temp end other = other.div(2) break if other == 0 temp.mprod!(a, a) temp, a = a, temp end ret when Float if self.symmetry? v, d = self.symmetrize.sym_evd d.diag.s_pow!(other) foo = v.mprod(d) d.mprod!(foo, v.t!) else raise UncomputableMatrixError, "cannot compute float power of non-symmetric matrcies" end when Rational self ** other.to_f else raise ArgumentError, "Mat powered by #{other.class} is not supported" end end |
#/(other) ⇒ Object
70 71 72 73 74 75 76 |
# File 'lib/kmat/arith.rb', line 70 def /(other) if other.kind_of?(Mat) raise ArgumentError, "Mat#/ is available only for scalar multiplication with reciprocal. To use Mat#/(Mat) as an alias of Mat#over, call `using Mat::MatrixProductOperator`" else self.dup.s_div!(other) end end |
#<(other) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/kmat/logical.rb', line 59 def <(other) return false if self.equal?(other) unless other.kind_of?(Mat) raise ArgumentError, "Mat < #{other.class} is not defined" end if self.vtype != other.vtype raise ValueTypeError, "value types must be the same" elsif self.size != other.size raise MismatchedDimensionError, "the sizes must be the same, (#{self.size.join(', ')}) != (#{other.size.join(', ')})" end each_with_index do |e, i, j| return false unless e < other[i, j] end true end |
#<=(other) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/kmat/logical.rb', line 74 def <=(other) return false if self.equal?(other) unless other.kind_of?(Mat) raise ArgumentError, "Mat <= #{other.class} is not defined" end if self.vtype != other.vtype raise ValueTypeError, "value types must be the same" elsif self.size != other.size raise MismatchedDimensionError, "the sizes must be the same, (#{self.size.join(', ')}) != (#{other.size.join(', ')})" end each_with_index do |e, i, j| return false unless e <= other[i, j] end true end |
#==(other) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/kmat/logical.rb', line 47 def ==(other) return true if self.equal?(other) return false unless other.kind_of?(Mat) if self.vtype == other.vtype && self.size == other.size each_with_index do |e, i, j| return false unless e == other[i, j] end true else false end end |
#===(other) ⇒ Object
2 3 4 5 6 7 8 |
# File 'lib/kmat/accessor.rb', line 2 def ===(other) if other.kind_of?(Mat) self == other else false end end |
#>(other) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/kmat/logical.rb', line 89 def >(other) return false if self.equal?(other) unless other.kind_of?(Mat) raise ArgumentError, "Mat > #{other.class} is not defined" end if self.vtype != other.vtype raise ValueTypeError, "value types must be the same" elsif self.size != other.size raise MismatchedDimensionError, "the sizes must be the same, (#{self.size.join(', ')}) != (#{other.size.join(', ')})" end each_with_index do |e, i, j| return false unless e > other[i, j] end true end |
#>=(other) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/kmat/logical.rb', line 104 def >=(other) return false if self.equal?(other) unless other.kind_of?(Mat) raise ArgumentError, "Mat > #{other.class} is not defined" end if self.vtype != other.vtype raise ValueTypeError, "value types must be the same" elsif self.size != other.size raise MismatchedDimensionError, "the sizes must be the same, (#{self.size.join(', ')}) != (#{other.size.join(', ')})" end each_with_index do |e, i, j| return false unless e >= other[i, j] end true end |
#[](*idx) ⇒ Object
10 11 12 13 14 15 16 17 18 19 |
# File 'lib/kmat/accessor.rb', line 10 def [](*idx) if block_given? tmp = self.bracket(*idx) ret = yield(tmp) tmp.__send__(:_kill) ret else self.bracket(*idx) end end |
#add(other) ⇒ Object Also known as: +
11 12 13 14 15 16 17 |
# File 'lib/kmat/arith.rb', line 11 def add(other) if other.kind_of?(Mat) self.dup.add!(broadcast(other)) else self.dup.s_add!(other) end end |
#add_times(other, alpha) ⇒ Object
78 79 80 81 82 83 84 |
# File 'lib/kmat/arith.rb', line 78 def add_times(other, alpha) if other.kind_of?(Mat) self.dup.add_times!(broadcast(other), alpha) else self.dup.s_mul!(other*alpha) end end |
#all?(*args) ⇒ Boolean
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/kmat/logical.rb', line 2 def all?(*args) if block_given? each do |ent| return false unless yield(ent, *args) end elsif args.size == 0 if self.vtype == :bool each do |ent| return false unless ent end else return enum_for(__method__) end else each do |ent| args.each do |arg| return false unless arg === ent end end end return true end |
#any?(*args) ⇒ Boolean
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/kmat/logical.rb', line 24 def any?(*args) if block_given? each do |ent| return true if yield(ent, *args) end elsif args.size == 0 if self.vtype == :bool each do |ent| return true if ent end else return enum_for(__method__) end else each do |ent| args.each do |arg| return true if arg === ent end end end return false end |
#broadcast(other, vt = nil) ⇒ Object
extend ‘other’ to fit the shape of self this is similar to Python’s numpy broadcasting
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 |
# File 'lib/kmat/accessor.rb', line 42 def broadcast(other, vt=nil) if other.kind_of?(Mat) if other.row_size == 1 if other.col_size == 1 other.repmat(row_size(), col_size()) elsif other.col_size == self.col_size other.repmat(self.row_size, 1) else raise MismatchedDimensionError, "can't broadcast from (#{other.size.join(', ')}) to (#{self.size.join(', ')})" end elsif other.row_size == self.row_size if other.col_size == 1 other.repmat(1, col_size()) elsif other.col_size == self.col_size other else raise MismatchedDimensionError, "can't broadcast from (#{self.size.join(', ')}) to (#{other.size.join(', ')})" end else raise MismatchedDimensionError, "can't broadcast from (#{self.size.join(', ')}) to (#{other.size.join(', ')})" end else vt = vtype() if vt.nil? Mat.new(row_size(), col_size(), vt).fill(other) end end |
#coerce(other) ⇒ Object
to define Numeric * Mat as Mat#scalar(Numeric) remaining Mat * Mat is undefined, this returns non‐standard value
4 5 6 7 8 9 10 |
# File 'lib/kmat/arith.rb', line 4 def coerce(other) if caller.first[/`([^']*)'/, 1] == '*' [self, other] else raise TypeError, "Mat can't be coerced into #{other.class}" end end |
#diag(k = 0) ⇒ Object
114 115 116 |
# File 'lib/kmat/accessor.rb', line 114 def diag(k=0) _diag_ul(k) end |
#distance(other) ⇒ Object
distance (Frobenius norm of the difference)
229 230 231 |
# File 'lib/kmat/linalg.rb', line 229 def distance(other) self.dup.sub!(other).normf end |
#e_div(other) ⇒ Object
34 35 36 37 38 39 40 |
# File 'lib/kmat/arith.rb', line 34 def e_div(other) if other.kind_of?(Mat) self.dup.e_div!(broadcast(other)) else self.dup.s_div!(other) end end |
#e_mul(other) ⇒ Object
27 28 29 30 31 32 33 |
# File 'lib/kmat/arith.rb', line 27 def e_mul(other) if other.kind_of?(Mat) self.dup.e_mul!(broadcast(other)) else self.dup.s_mul!(other) end end |
#eigen_values ⇒ Object
130 131 132 133 134 135 136 |
# File 'lib/kmat/linalg.rb', line 130 def eigen_values if symmetry? symmetrize().sym_eigen_values() else ge_eigen_values() end end |
#eq(other) ⇒ Object
120 121 122 123 124 125 |
# File 'lib/kmat/logical.rb', line 120 def eq(other) unless other.kind_of?(Mat) && other.size == self.size other = broadcast(other) end Mat.new(row_size(), col_size(), :bool).eq!(self, other) end |
#evd ⇒ Object
137 138 139 140 141 142 143 |
# File 'lib/kmat/linalg.rb', line 137 def evd if symmetry? symmetrize().sym_evd() else ge_evd() end end |
#flip(dim = :both) ⇒ Object
flip row, column or both axis ‘dim’ Symbol specifies fliping axis (:row, :col, :both, :none are available)
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 |
# File 'lib/kmat/accessor.rb', line 85 def flip(dim=:both) dim = dim.to_sym if dim.respond_to?(:to_sym) m, n = *shape() case dim when :both, :b ri = Mat.new(m, 1, :int) do |i, j| m-i-1 end ci = Mat.new(n, 1, :int) do |i, j| n-i-1 end self[ri, ci] when :row, :r ri = Mat.new(m, 1, :int) do |i, j| m-i-1 end self[ri, nil] when :col, :c ci = Mat.new(n, 1, :int) do |i, j| n-i-1 end self[nil, ci] when :none, :n self[] else raise ArgumentError, "unknown axis symbol #{dim.inspect}" end end |
#ge(other) ⇒ Object
144 145 146 147 148 149 |
# File 'lib/kmat/logical.rb', line 144 def ge(other) unless other.kind_of?(Mat) && other.size == self.size other = broadcast(other) end Mat.new(row_size(), col_size(), :bool).ge!(self, other) end |
#geo_mean(arg = :all) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/kmat/statistics.rb', line 87 def geo_mean(arg=:all) foo = self.log.mean(arg) if foo.kind_of?(Mat) foo.exp! elsif arg.kind_of?(Mat) arg.exp! arg[0, 0] else Math.exp(foo) end end |
#geo_normalize(arg = :all) ⇒ Object
48 49 50 |
# File 'lib/kmat/misc.rb', line 48 def geo_normalize(arg=:all) self.dup.geo_normalize!(arg) end |
#geo_normalize!(arg = :all) ⇒ Object
38 39 40 41 42 43 44 45 46 47 |
# File 'lib/kmat/misc.rb', line 38 def geo_normalize!(arg=:all) self.log! foo = self.mean(arg) if foo.kind_of?(Mat) self.sub!(self.broadcast(foo)) else self.s_sub!(foo) end self.exp! end |
#gt(other) ⇒ Object
138 139 140 141 142 143 |
# File 'lib/kmat/logical.rb', line 138 def gt(other) unless other.kind_of?(Mat) && other.size == self.size other = broadcast(other) end Mat.new(row_size(), col_size(), :bool).gt!(self, other) end |
#hypot(other) ⇒ Object
149 150 151 152 153 154 155 |
# File 'lib/kmat/arith.rb', line 149 def hypot(other) if other.kind_of?(Mat) self.dup.hypot!(broadcast(other)) else self.dup.s_hypot!(other) end end |
#iprod(*args, inverse: false) ⇒ Object Also known as: inner_product
inner product let x and y are column vectors and M is a square matrix the following is available (1) x.iprod => x’*x (2) x.iprod(y) => x’*y (3) M.iprod(x) => x’*M*x (4) M.iprod(x, y) => x’*M*y if ‘inverse’ is true, M is replaced by its Moore–Penrose inverse in case (1) or (2), ‘inverse’ is ignored if x or y is row vector, take transpose automatically
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/kmat/linalg.rb', line 155 def iprod(*args, inverse: false) case args.size when 0 if vector? # case 1 _iprod(self) else raise MismatchedDimensionError, "self must be a vector" end when 1 o = args[0] if o.vector? if vector? # case 2 _iprod(o) else # case 3 if !square? raise MismatchecDimensionError, "M must be square for M.iprod(x)" elsif inverse temp = Mat.new(row_size, 1, vtype) if o.col_size == 1 begin temp.solve!(self, o) rescue UncomputableMatrixError temp.ls!(self, o) end else begin temp.tsolve!(self, o) rescue UncomputableMatrixError temp.tls!(self, o) end end else temp = Mat.new(row_size, 1, vtype) if o.col_size == 1 temp.mprod!(self, o) else temp.mprod!(o, self) end end temp.__send__(:_iprod, o) end else raise MismatchedDimensionError, "as iprod with single argument, x.iprod(y) and M.iprod(x) are available, not x.iprod(M) or others" end when 2 # case 4 x, y = *args if !square? || !x.vector? || !y.vector? || x.length != row_size || y.length != row_size raise MismatchecDimensionError, "as iprod with 2 arguments, only M.iprod(x, y) is available, not others" end temp = Mat(row_size, 1, vtype) if y.col_size == 1 temp.mprod!(y) else if y.frozen? y = y.dup y.transpose temp.mprod!(y) else begin y.transpose temp.mprod!(y) ensure y.transpose end end end x.__send__(:_iprod, temp) else raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..2)" end end |
#le(other) ⇒ Object
132 133 134 135 136 137 |
# File 'lib/kmat/logical.rb', line 132 def le(other) unless other.kind_of?(Mat) && other.size == self.size other = broadcast(other) end Mat.new(row_size(), col_size(), :bool).le!(self, other) end |
#least_squares(b, tor: nil, weight: nil, transpose: false) ⇒ Object Also known as: ls
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/kmat/linalg.rb', line 18 def least_squares(b, tor: nil, weight: nil, transpose: false) if tor raise ArgumentError, "tor and weight must not specify at once" if weight raise ArgumentError, "for conjugate LS, auto-transpose is not available" if transpose ls_conj(b, tor) elsif weight raise ArgumentError, "for weighted LS, auto-transpose is not available" if transpose wls(b, weight) else if transpose tls(b) else Mat.new(*b.shape, :float).__send__(:_ls, self, b) end end end |
#least_squares!(a, b, tor: nil, weight: nil, transpose: false) ⇒ Object Also known as: ls!
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/kmat/linalg.rb', line 2 def least_squares!(a, b, tor: nil, weight: nil, transpose: false) if tor raise ArgumentError, "tor and weight must not specify at once" if weight raise ArgumentError, "for conjugate LS, auto-transpose is not available" if transpose _ls_conj(a, b, tor) elsif weight raise ArgumentError, "for weighted LS, auto-transpose is not available" if transpose wls!(a, b, weight) else if transpose tls!(a, b) else _ls(a, b) end end end |
#ls_conj(b, tor: Float::EPSILON) ⇒ Object
40 41 42 |
# File 'lib/kmat/linalg.rb', line 40 def ls_conj(b, tor: Float::EPSILON) Mat.new(self.col_size, 1, :float).ls_conj!(self, b, tor: tor) end |
#ls_conj!(a, b, tor: Float::EPSILON) ⇒ Object
37 38 39 |
# File 'lib/kmat/linalg.rb', line 37 def ls_conj!(a, b, tor: Float::EPSILON) _ls_conj(a, b, tor) end |
#lt(other) ⇒ Object
126 127 128 129 130 131 |
# File 'lib/kmat/logical.rb', line 126 def lt(other) unless other.kind_of?(Mat) && other.size == self.size other = broadcast(other) end Mat.new(row_size(), col_size(), :bool).lt!(self, other) end |
#maximum(other) ⇒ Object
86 87 88 89 90 91 92 |
# File 'lib/kmat/arith.rb', line 86 def maximum(other) if other.kind_of?(Mat) self.dup.maximum!(broadcast(other)) else self.dup.s_maximum!(other) end end |
#mean(arg = :all) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/kmat/statistics.rb', line 17 def mean(arg=:all) foo = sum(arg) if foo.kind_of?(Mat) if foo.row_size != self.row_size foo.e_div(self.row_size) else foo.e_div(self.col_size) end elsif arg.kind_of?(Mat) arg.e_div(self.length) arg[0, 0] else foo.quo(self.length) end end |
#minimum(other) ⇒ Object
93 94 95 96 97 98 99 |
# File 'lib/kmat/arith.rb', line 93 def minimum(other) if other.kind_of?(Mat) self.dup.minimum!(broadcast(other)) else self.dup.s_minimum!(other) end end |
#norm(type = :two, elementwise: false) ⇒ Object
matrix norm ‘type’ Symbol or Integer specifies norm definition if ‘elementwise’ is true, return induced norm if ‘elementwise’ is false, return elementwise norm if ‘type’ is :fro, return Frobenius norm
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/kmat/linalg.rb', line 241 def norm(type=:two, elementwise: false) if elementwise case type when :one, :o, 1 norm_e1() when :infinity, :i, :inf, :infty, Float::INFINITY norm_einf() when :two, :t, 2, :frobenius, :f, :fro normf() end else case type when :one, :o, 1 norm1() when :infinity, :i, :inf, :infty, Float::INFINITY normi() when :two, :t, 2 norm2() when :frobenius, :f, :fro normf() end end end |
#normalize ⇒ Object
65 66 67 |
# File 'lib/kmat/misc.rb', line 65 def normalize self.dup.normalize! end |
#normalize! ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/kmat/misc.rb', line 51 def normalize! if self.vector? self.s_div!(self.normf) elsif self.square? ev = self.eigen_values if ev[0] < 0 self.diag.s_add!(ev[0]*(-2)) ev.s_add!(ev[0]*(-2)) end self.s_div!(Math.exp(ev.log!.mean)) else raise MismatchedDimensionError, "normalize is available only for vectors or square matricies" end end |
#over(other) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/kmat/linalg.rb', line 95 def over(other) if other.square? begin other.tsolve(self).t! rescue UncomputableMatrixError other.tls(self).t! end else other.tls(self).t! end end |
#over!(a, b) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/kmat/linalg.rb', line 106 def over!(a, b) if b.square? begin tsolve!(b, a).t! rescue UncomputableMatrixError tls!(b, a).t! end else tls!(b, a).t! end end |
#pinv ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/kmat/linalg.rb', line 117 def pinv n = self.size.min i = Mat.I(n) if square? begin solve(i) rescue UncomputableMatrixError ls(i) end else ls(i) end end |
#pow(other) ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/kmat/arith.rb', line 101 def pow(other) if other.kind_of?(Mat) self.dup.pow!(broadcast(other)) else self.dup.s_pow!(other) end end |
#rand(arg = nil, random: $MatRandom) ⇒ Object
92 93 94 |
# File 'lib/kmat/random.rb', line 92 def rand(arg=nil, random: $MatRandom) _rand0(random, arg) end |
#rand_orth(random: $MatRandom) ⇒ Object
66 67 68 |
# File 'lib/kmat/linalg.rb', line 66 def rand_orth(random: $MatRandom) _rand_orth(random) end |
#randn(random: $MatRandom) ⇒ Object
95 96 97 |
# File 'lib/kmat/random.rb', line 95 def randn(random: $MatRandom) _randn0(random) end |
#rcond(type = :two) ⇒ Object
265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/kmat/linalg.rb', line 265 def rcond(type=:two) case type when :one, :o, 1 _rcondoi(:one) when :infinity, :i, :inf, :infty, Float::INFINITY _rcondoi(:infinity) when :two, :t, 2 _rcond2() when :frobenius, :f, :fro _rcondf() end end |
#replace_rep(src) ⇒ Object
replace self by repeated ‘src’ self will be left-top of infinitly repeated ‘src’
71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/kmat/accessor.rb', line 71 def replace_rep(src) ri = Mat.new(row_size(), 1, :int) do |i, j| i % src.row_size end ci = Mat.new(col_size(), 1, :int) do |i, j| i % src.col_size end src[ri, ci] do |m| self.copy_from(m) end end |
#repmat(row_repeat, col_repeat) ⇒ Object
for example, A.repmat(2, 3) returns [A, A, A: A, A, A]
28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/kmat/accessor.rb', line 28 def repmat(row_repeat, col_repeat) ri = Mat.new(row_size()*row_repeat, 1, :int) do |i, j| i % row_size() end ci = Mat.new(col_size()*col_repeat, 1, :int) do |i, j| i % col_size() end self[ri, ci] do |m| m.dup end end |
#rpow(other) ⇒ Object
108 109 110 |
# File 'lib/kmat/arith.rb', line 108 def rpow(other) other.dup.pow!(other.broadcast(self)) end |
#save(file) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/kmat/misc.rb', line 24 def save(file) case file when String File.open(file, 'w') do |f| Marshal.dump(self, f) end when IO Marshal.dump(self, file) else raise ArgumentError, 'the argument must be a filepath or an IO object' end nil end |
#scalar(alpha) ⇒ Object
66 67 68 |
# File 'lib/kmat/arith.rb', line 66 def scalar(alpha) self.dup.s_mul!(alpha) end |
#squared_distance(other) ⇒ Object
232 233 234 |
# File 'lib/kmat/linalg.rb', line 232 def squared_distance(other) self.dup.sub!(other).iprod end |
#std(arg = :all, ddof: 0) ⇒ Object Also known as: stddev, standard_deviation
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/kmat/statistics.rb', line 73 def std(arg=:all, ddof: 0) foo = var(arg, ddof: ddof) if foo.kind_of?(Mat) foo.sqrt! elsif arg.kind_of?(Mat) arg.sqrt! arg[0, 0] else Math.sqrt(arg) end end |
#sub(other) ⇒ Object Also known as: -
19 20 21 22 23 24 25 |
# File 'lib/kmat/arith.rb', line 19 def sub(other) if other.kind_of?(Mat) self.dup.sub!(broadcast(other)) else self.dup.s_sub!(other) end end |
#sum(arg = :all) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# File 'lib/kmat/statistics.rb', line 2 def sum(arg=:all) case arg when Mat _sum(arg) when :all, :a _sum(Mat.new(1, 1, self.vtype)) when :col, :c _sum(Mat.new(1, col_size, self.vtype)) when :row, :r _sum(Mat.new(row_size, 1, self.vtype)) when :none, :n self.dup end end |
#temp ⇒ Object
21 22 23 24 25 |
# File 'lib/kmat/accessor.rb', line 21 def temp ret = yield(self) _kill ret end |
#under(other) ⇒ Object
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/kmat/linalg.rb', line 73 def under(other) if square? begin solve(other) rescue UncomputableMatrixError ls(other) end else ls(other) end end |
#under!(a, b) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/kmat/linalg.rb', line 84 def under!(a, b) if a.square? begin solve!(a, b) rescue UncomputableMatrixError ls!(a, b) end else ls!(a, b) end end |
#var(arg = :all, ddof: 0) ⇒ Object Also known as: variance
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/kmat/statistics.rb', line 48 def var(arg=:all, ddof: 0) foo = mean(arg) if foo.kind_of?(Mat) = foo.repmat(self.row_size.div(foo.col_size), self.col_size.div(foo.col_size)) .sub!(self).e_mul!() else unless arg.kind_of?(Mat) arg = Mat.new(1, 1, self.vtype) do foo end end = Mat.new(self.row_size, self.col_size, self.vtype) .fill(foo) end .sub!(self) .e_mul!() .__send__(:_mean, arg, ddof) if foo.kind_of?(Mat) else [0, 0] end end |
#wls(b, w) ⇒ Object
62 63 64 |
# File 'lib/kmat/linalg.rb', line 62 def wls(b, w) Mat.new(self.col_size, 1, :f).wls!(self, b, w) end |
#wls!(a, b, w) ⇒ Object
weighted least squares weight ‘w’ is a vector consists of standard deviations of errors a; (m, n)-matrix b: m-vector x: n-vector
49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/kmat/linalg.rb', line 49 def wls!(a, b, w) nw = w.length diag = Mat.new(nw, nw, :f) diag.diag.temp do |dd| begin dd.copy_from(w) rescue MismatchedDimensionError dd.tcopy_from(w) end dd.sqrt! end glm!(a, diag, b) end |