stair_car 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gitignore +21 -0
  2. data/Gemfile +14 -0
  3. data/Guardfile +18 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +223 -0
  6. data/Rakefile +1 -0
  7. data/lib/matlab/matlabcontrol-4.0.0.jar +0 -0
  8. data/lib/pcolt/lib/arpack-combo.jar +0 -0
  9. data/lib/pcolt/lib/csparsej.jar +0 -0
  10. data/lib/pcolt/lib/jplasma.jar +0 -0
  11. data/lib/pcolt/lib/jtransforms.jar +0 -0
  12. data/lib/pcolt/lib/junit.jar +0 -0
  13. data/lib/pcolt/lib/netlib-java.jar +0 -0
  14. data/lib/pcolt/lib/optimization.jar +0 -0
  15. data/lib/pcolt/parallelcolt-0.9.4.jar +0 -0
  16. data/lib/stair_car/mmatrix/matlab_interface.rb +9 -0
  17. data/lib/stair_car/mmatrix/mmatrix.rb +26 -0
  18. data/lib/stair_car/pmatrix/compare.rb +34 -0
  19. data/lib/stair_car/pmatrix/matrix_math.rb +169 -0
  20. data/lib/stair_car/pmatrix/pmatrix.rb +151 -0
  21. data/lib/stair_car/pmatrix/transforms.rb +74 -0
  22. data/lib/stair_car/pmatrix/types.rb +106 -0
  23. data/lib/stair_car/shared/errors.rb +7 -0
  24. data/lib/stair_car/shared/indicies.rb +33 -0
  25. data/lib/stair_car/shared/init_methods.rb +56 -0
  26. data/lib/stair_car/shared/inspect.rb +113 -0
  27. data/lib/stair_car/shared/iteration.rb +32 -0
  28. data/lib/stair_car/umatrix/compare.rb +34 -0
  29. data/lib/stair_car/umatrix/matrix_math.rb +190 -0
  30. data/lib/stair_car/umatrix/transforms.rb +49 -0
  31. data/lib/stair_car/umatrix/types.rb +42 -0
  32. data/lib/stair_car/umatrix/umatrix.rb +166 -0
  33. data/lib/stair_car.rb +35 -0
  34. data/lib/ujmp/ujmp-complete-0.2.5.jar +0 -0
  35. data/spec/pmatrix/matrix_math_spec.rb +65 -0
  36. data/spec/pmatrix/pmatrix_spec.rb +103 -0
  37. data/spec/pmatrix/transforms_spec.rb +44 -0
  38. data/spec/shared/indicies_spec.rb +52 -0
  39. data/spec/shared/inspect_spec.rb +23 -0
  40. data/spec/shared/iteration_spec.rb +17 -0
  41. data/spec/spec_helper.rb +5 -0
  42. data/spec/umatrix/matrix_math_spec.rb +68 -0
  43. data/spec/umatrix/transform_spec.rb +32 -0
  44. data/spec/umatrix/umatrix_spec.rb +104 -0
  45. data/stair_car.gemspec +19 -0
  46. metadata +120 -0
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rvmrc
19
+ .idea
20
+ *.DS_Store
21
+ lib/.DS_Store
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in pmatrix.gemspec
4
+ gemspec
5
+
6
+
7
+ group :development do
8
+ gem 'guard'
9
+ gem 'rb-inotify', :require => false
10
+ gem 'rb-fsevent', :require => false
11
+ gem 'rb-fchange', :require => false
12
+ gem 'guard-rspec'
13
+ gem 'terminal-notifier-guard'
14
+ end
data/Guardfile ADDED
@@ -0,0 +1,18 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ # watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec" }
8
+ watch('spec/spec_helper.rb') { "spec" }
9
+
10
+ # # Rails example
11
+ # watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
12
+ # watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
13
+ # watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
14
+ # watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
15
+ # watch('config/routes.rb') { "spec/routing" }
16
+ # watch('app/controllers/application_controller.rb') { "spec/controllers" }
17
+ end
18
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ryan Stout
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # StairCar
2
+
3
+ StairCar is a matlab or numpy like matrix library gem for jruby. It provides several matrix classes that wrap different Java based matrix libraries in a simple ruby interface. It overloads ruby operators to provide a matlab like functionality.
4
+
5
+ # Goals
6
+
7
+ StairCar should be:
8
+
9
+ - Rubyish (object oriented, use operator overloading for math operations)
10
+ - Fast (use optimized underlying storage/algebra systems, use BLAS where available)
11
+ - Unified (It should provide a standard interface across multiple internal implementations)
12
+
13
+ StairCar is geared towards two dimensional matrices and treats vectors as a 1 by M or N x 1 matrix. StairCar currently does not support >2 dimensional matrices. It also currently only supports double and float matrices. Though support for integer and boolean matrices is planned.
14
+
15
+ ## Features
16
+
17
+ - Dense and Sparse matrices (with 2^64 elements)
18
+ - Ability to efficiently iterate on non-zero elements in sparse matrices
19
+ - Subviews (that reference the original matrix)
20
+ - Matrix, vector, and scalar add, sub, mul, div, and matrix multiply. (In any combination)
21
+ - Easy iteration on rows, cols, or elements
22
+ - Element wise comparison >,>=,<,<= that returns a 1/0 matrix
23
+ - Mathematical operations on the full matrix, rows, or cols (currently only std, variance, mean, max, min)
24
+ - Shortcuts for making matricies (zeros, spzeros, rand, ones, asc, desc, etc...)
25
+ - .dup to copy
26
+ - == to compare values
27
+ - A good clean inspect
28
+
29
+
30
+ ## Usage
31
+
32
+ Once you have required stair_car, you will have access to two matrix classes (currently): PMatrix and UMatrix. PMatrix wraps the pcolt library and is good for sparse matrices. UMatrix wraps the ujmp library, which its self wraps many java libraries. Currently UMatrix support is still a work in progress.
33
+
34
+ ### Basic Usage
35
+
36
+ To start, include the StairCar module into your current class
37
+
38
+ include StairCar
39
+
40
+ This provides you with many shortcut methods to make matricies:
41
+
42
+ Dense: zeros, ones, rand, asc, desc
43
+ Sparse: spzeros, spones, sprand, spasc, spdesc
44
+
45
+ m = asc(3,3)
46
+ => <#PMatrix(double) 3x3 dense>
47
+ 1 2 3
48
+ 4 5 6
49
+ 7 8 9
50
+
51
+ ### Get elements
52
+
53
+ You can get any element by passing in its row and column:
54
+
55
+ m[0,1]
56
+ => 2
57
+
58
+ ### Subviews
59
+
60
+ StairCar supports many options to generate subviews. You can pass in the following:
61
+
62
+ - Arrays - Selects a row/column, treating the integer in the array as a row or column index.
63
+ - Ranges - Selects each row/column index within the range
64
+ - nil - Selects the whole row/column
65
+ - You can also pass in a combination of arrays and ranges.
66
+
67
+ For example:
68
+
69
+ m[0..1,nil]
70
+ => <#PMatrix() 2x3 dense>
71
+ 1 2 3
72
+ 4 5 6
73
+
74
+ ### Assignment
75
+
76
+ You can assign a single element:
77
+
78
+ m[0,1] = 22.5
79
+
80
+ m
81
+ => <#PMatrix(double) 3x3 dense>
82
+ 1 22.5 3
83
+ 4 5 6
84
+ 7 8 9
85
+
86
+ You can assign a scalar to every value in a subview
87
+
88
+ # Assign a row (row 0, all columns)
89
+ m[0,nil] = 2
90
+
91
+ => <#PMatrix(double) 3x3 dense>
92
+ 2 2 2
93
+ 4 5 6
94
+ 7 8 9
95
+
96
+ You can assign an array or other matrix to a subview
97
+
98
+ # Assign an array to a row
99
+ m[0..1,nil] = [[1,2,3],[4,5,6]]
100
+
101
+ => <#PMatrix(double) 3x3 dense>
102
+ 1 2 3
103
+ 4 5 6
104
+ 7 8 9
105
+
106
+ # Multiple row or column subviews
107
+ m[[1,2],2]
108
+ => <#PMatrix() 2x1 dense>
109
+ 6
110
+ 9
111
+
112
+ ### Math
113
+
114
+ Math is simple, just use the standard +,-,/ * does matrix multiplication and ** does element wise multiplication.
115
+
116
+ a = asc(3,3)
117
+ b = asc(3,3)
118
+
119
+ a + b
120
+ => <#PMatrix(double) 3x3 dense>
121
+ 2 4 6
122
+ 8 10 12
123
+ 14 16 18
124
+
125
+ a * b
126
+ => <#PMatrix(double) 3x3 dense>
127
+ 30 36 42
128
+ 66 81 96
129
+ 102 126 150
130
+
131
+ a ** b
132
+ => <#PMatrix(double) 3x3 dense>
133
+ 1 4 9
134
+ 16 25 36
135
+ 49 64 81
136
+
137
+ ### Transpose and inverse
138
+
139
+ Transpose can be done with either matrix.transpose or ~matrix
140
+
141
+ ### Stats
142
+
143
+ All stats operations can operate on the whole matrix, or just the columns or the rows. Just pass in a dimension to specify cols or rows (rows = 0, cols = 1)
144
+
145
+ m = asc(3,3)
146
+ m.sum
147
+ => 45.0
148
+
149
+ m.sum(0)
150
+ => <#PMatrix(double) 1x3 dense>
151
+ 12 15 18
152
+
153
+ m.sum(1)
154
+ => <#PMatrix(double) 3x1 dense>
155
+ 6
156
+ 15
157
+ 24
158
+
159
+ Supported operations
160
+
161
+ - sum
162
+ - max
163
+ - min
164
+ - mean
165
+ - variance
166
+ - std
167
+
168
+ ### Iteration
169
+
170
+ Matrices support the standard ruby each, each_with_index, and map operations. However each passes in a value, row, col instead of just a value.
171
+
172
+ It also supports each_column and each_row
173
+
174
+ You can also iterate or map on non-zero elements, which makes mapping sparse matrices much more efficient. Use #each_non_zero, #map_non_zero, or #map_non_zero! Using ! on the end of map or map_non_zero means all updates will happen to the original matrix, thus saving memory.
175
+
176
+ m = spzeros(5,5)
177
+ => <#PMatrix(double) 5x5 sparse>
178
+ 0 0 0 0 0
179
+ 0 0 0 0 0
180
+ 0 0 0 0 0
181
+ 0 0 0 0 0
182
+ 0 0 0 0 0
183
+
184
+ m[0,2] = 5
185
+ m[3,4] = 10
186
+
187
+ m
188
+ => <#PMatrix(double) 5x5 sparse>
189
+ 0 0 5 0 0
190
+ 0 0 0 0 0
191
+ 0 0 0 0 0
192
+ 0 0 0 0 10
193
+ 0 0 0 0 0
194
+
195
+ m.map_non_zero! {|value,row,col| value * 2 }
196
+ => <#PMatrix(double) 5x5 sparse>
197
+ 0 0 10 0 0
198
+ 0 0 0 0 0
199
+ 0 0 0 0 0
200
+ 0 0 0 0 20
201
+ 0 0 0 0 0
202
+
203
+ ## Planned Features
204
+
205
+ - JBLAS support
206
+ - MRI support (perhaps with NMatrix)
207
+ - More statistical features
208
+
209
+
210
+ ## Installation
211
+
212
+ Add this line to your application's Gemfile:
213
+
214
+ gem 'stair_car'
215
+
216
+ And then execute:
217
+
218
+ $ bundle
219
+
220
+ Or install it yourself as:
221
+
222
+ $ gem install stair_car
223
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../../matlab/matlabcontrol-4.0.0'
2
+ class MatlabInterface
3
+ def initialize
4
+ factory = Java::Matlabcontrol::MatlabProxyFactory.new
5
+ @proxy = factory.proxy
6
+ @processor = Java::matlabcontrol.extensions.MatlabTypeConverter.new(@proxy)
7
+ end
8
+
9
+ end
@@ -0,0 +1,26 @@
1
+ require 'stair_car/types'
2
+ require 'stair_car/inspect'
3
+ require 'stair_car/indicies'
4
+ require 'stair_car/iteration'
5
+ require 'stair_car/matrix_math'
6
+ require 'stair_car/transforms'
7
+ require 'stair_car/compare'
8
+
9
+ class MMatrix
10
+ # include Types
11
+ # include Inspect
12
+ # include Indicies
13
+ # include Iteration
14
+ # include MatrixMath
15
+ # include Transforms
16
+ # include Compare
17
+
18
+ def initialize
19
+ @@mi ||= MatlabInterface.new
20
+ end
21
+
22
+ def [](rows, cols)
23
+
24
+
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ module StairCar
2
+ module PMatrixCompare
3
+ def >(val)
4
+ map {|v| (v > val) ? 1 : 0 }
5
+ end
6
+
7
+ def >=(val)
8
+ map {|v| (v >= val) ? 1 : 0 }
9
+ end
10
+
11
+ def <(val)
12
+ map {|v| (v < val) ? 1 : 0 }
13
+ end
14
+
15
+ def <=(val)
16
+ map {|v| (v <= val) ? 1 : 0 }
17
+ end
18
+
19
+ def find(matrix)
20
+
21
+ end
22
+
23
+ def any?
24
+ @data.cardinality > 0
25
+ end
26
+
27
+
28
+ # Compares this matrix to another to see if they are the same (in values)
29
+ def ==(matrix2)
30
+ self.data.equals(matrix2.data)
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,169 @@
1
+ module StairCar
2
+ module PMatrixMatrixMath
3
+ class MatrixMathError < RuntimeError
4
+ end
5
+
6
+ def perform(val, &block)
7
+ result = @data.copy
8
+ if val.is_a?(PMatrix)
9
+ if rows == val.rows && cols == val.cols
10
+ # Another matrix of the same size
11
+ result = result.assign(val.data, &block)
12
+ elsif rows == val.rows && val.cols == 1
13
+ # Vector on column (vertical)
14
+ PMatrix.new(result).each_column do |row|
15
+ row.data.assign(val.data, &block)
16
+ end
17
+ elsif cols == val.cols && val.rows == 1
18
+ # Vector on rows (horizontal)
19
+ PMatrix.new(result).each_row do |col|
20
+ col.data.assign(val.data, &block)
21
+ end
22
+ else
23
+ # Incorrect size
24
+ raise MatrixMathError, "matrix dimensions incorrect"
25
+ end
26
+ else
27
+ # Passed in a number
28
+ perform_on_val = Proc.new do |cell_value|
29
+ yield(cell_value, val)
30
+ end
31
+
32
+ result.assign(perform_on_val)
33
+ end
34
+
35
+ return PMatrix.new(result)
36
+ end
37
+
38
+ def +(val)
39
+ perform(val) { |a,b| a + b }
40
+ # perform(val, Java::cern.jet.math.tdouble.DoubleFunctions.plus)
41
+ end
42
+
43
+ def -(val)
44
+ perform(val) { |a,b| a - b }
45
+ end
46
+
47
+ def **(val)
48
+ perform(val) { |a,b| a * b }
49
+ end
50
+
51
+ def /(val)
52
+ perform(val) { |a,b| a / b }
53
+ end
54
+
55
+ def *(val)
56
+ n = self.rows
57
+ m = self.cols
58
+
59
+ p = val.rows
60
+ q = val.cols
61
+
62
+ if m != p
63
+ raise MatrixMathError, "matricies can not be multiplied"
64
+ end
65
+
66
+ # Build a like matrix to receive
67
+ c = @data.like(n, q)
68
+
69
+ @data.z_mult(val.data, c)
70
+
71
+ return PMatrix.new(c)
72
+ end
73
+
74
+ def sum(dimension=nil)
75
+ if dimension == 0
76
+ # Sum rows
77
+ return PMatrix.ones(1, rows) * self
78
+ elsif dimension == 1
79
+ # Sum cols
80
+ return self * PMatrix.ones(cols, 1)
81
+ else
82
+ return @data.z_sum
83
+ end
84
+ end
85
+
86
+ def max(dimension=nil)
87
+ if dimension
88
+ value = aggrate_on_dimension(:max, dimension)
89
+ else
90
+ value, row, col = @data.max_location
91
+ end
92
+
93
+ return value
94
+ end
95
+
96
+ def min(dimension=nil)
97
+ if dimension
98
+ value = aggrate_on_dimension(:min, dimension)
99
+ else
100
+ value, row, col = @data.min_location
101
+ end
102
+
103
+ return value
104
+ end
105
+
106
+ def mean(dimension=nil)
107
+ if dimension
108
+ value = aggrate_on_dimension(:mean, dimension)
109
+ else
110
+ value = self.sum / self.size
111
+ end
112
+
113
+ return value
114
+ end
115
+
116
+ def variance(dimension=nil, sample=false)
117
+ if dimension
118
+ value = aggrate_on_dimension(:variance, dimension, sample)
119
+ else
120
+ mean = self.mean
121
+ total = 0
122
+ self.each_non_zero do |v|
123
+ total += (mean - v) ** 2
124
+ end
125
+
126
+ if sample
127
+ value = total / (self.size - 1)
128
+ else
129
+ value = total / self.size
130
+ end
131
+ end
132
+
133
+ return value
134
+ end
135
+
136
+ def std(dimension=nil, sample=false)
137
+ if dimension
138
+ value = aggrate_on_dimension(:variance, dimension, sample)
139
+ else
140
+ value = Math.sqrt(self.variance(dimension, sample))
141
+ end
142
+
143
+ return value
144
+ end
145
+
146
+ private
147
+ def aggrate_on_dimension(method_name, dimension, *args)
148
+ if dimension == 1
149
+ # Get the per row
150
+ vals = PMatrix.new(@data.like(rows, 1))
151
+
152
+ self.each_row do |row, row_number|
153
+ vals[row_number,0] = row.send(method_name, nil, *args).to_f
154
+ end
155
+
156
+ return vals
157
+ elsif dimension == 0
158
+ # Get the per row
159
+ vals = PMatrix.new(@data.like(1, cols))
160
+
161
+ self.each_column do |col, col_number|
162
+ vals[0,col_number] = col.send(method_name, nil, *args).to_f
163
+ end
164
+
165
+ return vals
166
+ end
167
+ end
168
+ end
169
+ end