csrmatrix 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5239814e3bf4d761150bacbe7d8fa44ca321446d
4
- data.tar.gz: 6f72c0b95e218e513b7372e1264054ea33c36ad2
3
+ metadata.gz: 842f69d5be23f5b6a2ea2057504f416eff0648f8
4
+ data.tar.gz: f05e25a4c9f740e9691e94bc3aeb6b4a476be910
5
5
  SHA512:
6
- metadata.gz: 0f1313cec202a6ca9d303229629615d0422342847e1b1f1e446c704f806b1aecf574c2945ae51e93158387dba3a020e992f9e3983b4aafa7d23b911060b9a566
7
- data.tar.gz: 1734545e1f6a6f2387466768bd62896757935deb648f002077e84bce4b972928f67c5a7af678cd8ad503fbe0d1300bc33b820b83fcd35296305dbdb04bfc16e4
6
+ metadata.gz: 767ba6ea5d5bdad6e30e986c052f93b6bd9b3822f28ee98326b132bc9010c01e3a17241ed7fe7ba558395e8853aca3fe9fd782ff36efa77fd43b0fbab825fd7c
7
+ data.tar.gz: 73afd742117835704942a8cf5202a1cbbd9e3c8eecf013709957191707ca38b9a5574e56082477d7ab6491b95cea71049718a4145699bfc1636c21029a83acfa
data/Gemfile CHANGED
@@ -2,5 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in matrix.gemspec
4
4
  gem "minitest"
5
+ gem "contracts"
5
6
 
6
7
  gemspec
data/Gemfile.lock CHANGED
@@ -1,11 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- csrmatrix (1.0.0)
4
+ csrmatrix (1.0.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ contracts (0.13.0)
9
10
  diff-lcs (1.2.5)
10
11
  minitest (5.8.3)
11
12
  rake (10.5.0)
@@ -28,6 +29,7 @@ PLATFORMS
28
29
 
29
30
  DEPENDENCIES
30
31
  bundler (~> 1.11)
32
+ contracts
31
33
  csrmatrix!
32
34
  minitest
33
35
  rake (~> 10.0)
data/README.md CHANGED
@@ -22,7 +22,112 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ ## Usage
26
+ #### Construction
27
+
28
+ Start by building the matrix object. This will be a simple shell, on which we can perform our operations on:
29
+
30
+ ```ruby
31
+ @matrix = TwoDMatrix.new
32
+ => #<TwoDMatrix:0x007fa5b2083ba8 @nonzero_count=nil, @row_ptr=nil, @col_ind=nil, @val=nil, @rows=0, @columns=0, @ndim=2>
33
+ ```
34
+
35
+ Then, we can fill it out using a variety of manners - either building the functions from arrays:
36
+
37
+ ```ruby
38
+ @matrix.build_from_array([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
39
+ @matrix.build_from_rows([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
40
+ @matrix.build_from_columns([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
41
+ @matrix.build_from_csr([0, 3, 6, 9],[0, 1, 2, 0, 1, 2, 0, 1, 2],[1, 2, 3, 1, 2, 3, 1, 2, 3],3,3)
42
+ ```
43
+
44
+ Or from an existing matrix using Ruby's matrix library:
45
+ ```ruby
46
+ @MatrixBuild = Matrix.rows([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
47
+ @matrix.build_from_matrix(@MatrixBuild)
48
+ ```
49
+
50
+ Or by generating a zero or identity matrix:
51
+ ```ruby
52
+ @matrix.build_zero_matrix(3, 2)
53
+ @matrix.build_identity_matrix(3)
54
+ ```
55
+
56
+ For more experienced users, build calls can be generated using keywords:
57
+ ```ruby
58
+ @matrix.build("rows", [[1, 2, 3], [1, 2, 3], [1, 2, 3]])
59
+ @matrix.build("columns", [[1, 2, 3], [1, 2, 3], [1, 2, 3]])
60
+ @matrix.build("identity", 3) #rows, columns are same
61
+ @matrix.build("zero", 2) #rows, columns
62
+ @matrix.build("csr", [[0, 3, 6, 9],[0, 1, 2, 0, 1, 2, 0, 1, 2],[1, 2, 3, 1, 2, 3, 1, 2, 3],3,3])
63
+ @matrix.build("array", [[1, 2, 3], [1, 2, 3], [1, 2, 3]])
64
+ @matrix.build("matrix", @MatrixBuild)
65
+ ```
66
+
67
+ #### Properties
68
+ CsrMatrix offers many property checks for matrices. Test the system by using the following code:
69
+ ```ruby
70
+ @matrixTrigonal3x3.diagonal?
71
+ ```
72
+
73
+ The list of usable properties, as of this point, are as follows:
74
+ ```ruby
75
+ .diagonal? .empty? .lower_triangular? .normal? .orthogonal? .permutation? .real? .nonsingular? .singular? .square? .symmetric? .unitary? .upper_ .triangular? .zero?
76
+ ```
77
+
78
+ #### Arithmetic
79
+ CsrMatrix offers the full suite of standard arithmetic processes for matrices. With regards to scalar operations:
80
+ ```ruby
81
+ @matrixConst.scalar_multiply(2)
82
+ @matrixConst.scalar_add(2)
83
+ @matrixConst.scalar_subtract(1)
84
+ @matrixConst.scalar_division(2)
85
+ @matrixConst.scalar_exp(2)
86
+ ```
87
+
88
+ As for matrix-to-matrix processes:
89
+ ```ruby
90
+ @matrixa.multiply_csr(@matrixb)
91
+ @matrixa.matrix_add(@matrixb)
92
+ @matrixa.is_same_dim(@matrixb)
93
+ @matrixa.matrix_add(@matrixb)
94
+ @matrixa.matrix_subtract(@matrixb)
95
+ @matrixa.matrix_inverse_multiply(@matrixd)
96
+ @matrixa.matrix_multiply_inverse(@matrixd)
97
+ @matrixa.matrix_division(@matrixd)
98
+ ```
99
+
100
+ And for others:
101
+ ```ruby
102
+ @matrixConst.inverse()
103
+ @matrixConst.transpose()
104
+ ```
105
+
106
+ #### Other
107
+ CsrMatrix offers standard display and assorted property assertion functions for your sparse matrix:
108
+
109
+ ```ruby
110
+ @matrixSparse3x3.print_full()
111
+ @matrixSparse3x3.print_sparse()
112
+ @matrixSparse3x3.get_value(4)
113
+ @matrixSparse3x3.index(1,1)
114
+ @matrixSparse3x3.det()
115
+ @matrixSparse3x3.determinant()
116
+ @matrixSparse3x3.rank()
117
+ @matrixFloat2x2.decompose()
118
+ @matrixDense3x3.trace()
119
+ @matrixDense3x3.tr()
120
+ @matrixSparse3x3.transpose()
121
+ @matrixSparse3x3.t()
122
+ ```
123
+
124
+ #### Exporting CsrMatrix
125
+ If you would like to integrate the matrix with your other code, you can simply disassemble it and reconstruct it at your leisure:
126
+
127
+ ```ruby
128
+ @matrix.decompose()
129
+ @matrix.decomp_to_matrix()
130
+ ```
26
131
 
27
132
  ## Development
28
133
 
Binary file
@@ -1,91 +1,130 @@
1
1
  require "matrix"
2
2
  require "csrmatrix/exceptions"
3
+ require "contracts"
4
+ require "csrmatrix/mcontracts"
3
5
 
4
6
  module CsrMatrix
5
7
  module Arithmetic
8
+ include Contracts::Core
9
+ C = Contracts
6
10
 
11
+ # Brings in exception module for exception testing
7
12
  def self.included(exceptions)
8
13
  exceptions.send :include, Exceptions
9
14
  end
10
15
 
11
- # class MatrixDimException < StandardError; end
12
- # class ArgumentNullException < StandardError; end
13
- # class MatrixTypeException < StandardError; end
14
-
15
- # REFERENCE: To use module functions in module
16
- # Class.new.extend(Decompositions).lup()
17
-
16
+ Contract C::Num => C::ArrayOf[C::Num]
18
17
  def scalar_multiply(value)
19
- if value == nil
20
- raise ArgumentNullException.new, "Multiply by nil error."
21
- return false
22
- end
18
+ # multiply the matrix by a scalar value
19
+ is_invariant?
20
+
23
21
  @val.each_index do |i|
24
22
  @val[i] = @val[i] * value
25
23
  end
26
- end
24
+ end # scalar_multiply
27
25
 
26
+ Contract C::Num => C::ArrayOf[C::Num]
28
27
  def scalar_add(value)
29
- if value == nil
30
- raise ArgumentNullException.new, "Add by nil error."
31
- return false
32
- end
33
- # create an identity matrix with the value
34
- # matrix_add the new identity matrix to the given matrix
28
+ # manipulate the matrix by adding a value at each index
29
+ is_invariant?
30
+
35
31
  @val.each_index do |i|
36
32
  @val[i] = @val[i] + value
37
33
  end
38
- end
34
+ end # scalar_add
39
35
 
36
+ Contract C::Num => C::ArrayOf[C::Num]
40
37
  def scalar_subtract(value)
41
- if value == nil
42
- raise ArgumentNullException.new, "Subtract by nil error."
43
- return false
44
- end
45
- # create an identity matrix with the value
46
- # matrix_subtract the new identity matrix to the given matrix
38
+ is_invariant?
39
+
40
+ # manipulate the matrix by subtracting the value at each index
47
41
  @val.each_index do |i|
48
42
  @val[i] = @val[i] - value
49
43
  end
50
- end
44
+ end # scalar_subtract
51
45
 
46
+ Contract C::Num => C::ArrayOf[C::Or[Float, Float]]
52
47
  def scalar_division(value)
53
- if value == nil
54
- raise ArgumentNullException.new, "Divide by nil error."
55
- return false
56
- end
48
+ is_invariant?
49
+ # manipulate the matrix by dividing the value at each index
50
+ # post boolean, updated matrix (in floats, if previously was not)
57
51
  @val.each_index do |i|
58
52
  @val[i] = @val[i] / value.to_f
59
53
  end
60
- end
54
+ end # scalar_division
61
55
 
56
+ Contract C::Num => C::ArrayOf[C::Num]
62
57
  def scalar_exp(value)
63
- if value == nil
64
- raise ArgumentNullException.new, "Exp. by nil error."
65
- return false
66
- end
58
+ is_invariant?
59
+ # manipulate the matrix by finding the exponential at each index
67
60
  @val.each_index do |i|
68
61
  @val[i] = @val[i] ** value
69
62
  end
70
- end
63
+ end # scalar_exp
71
64
 
65
+ Contract C::Num => C::Bool
72
66
  def inverse()
67
+ is_invariant?
68
+ # sets the inverse of this matrix
69
+ # pre existing matrix (matrix.not_null?)
70
+ # post inverted matrix
73
71
  m = Matrix.rows(self.decompose)
74
72
  self.build_from_array(m.inv().to_a())
75
- end
73
+ end # inverse
76
74
 
77
- # FIXME: Convert with CSR functions
75
+ Contract C::None => C::ArrayOf[C::Num]
78
76
  def transpose()
79
- m = Matrix.rows(self.decompose)
80
- self.build_from_array(m.transpose.to_a())
81
- end
77
+ is_invariant?
78
+ # transpose the matrix
79
+
80
+ new_row_ptr = Array.new(self.columns+1, 0)
81
+ new_col_ind = Array.new(self.col_ind.count(), 0)
82
+ new_val = Array.new(self.val.count(), 0)
83
+ current_row = 0
84
+ current_column = 0
85
+
86
+ for i in 0..self.columns-1
87
+ for j in 0..self.col_ind.count(i)-1
88
+ # get the row
89
+ index = self.col_ind.find_index(i)
90
+ self.col_ind[index] = -1
91
+ for k in 1..self.row_ptr.count()-1
92
+ if self.row_ptr[k-1] <= index && index < self.row_ptr[k]
93
+ current_row = k
94
+ break
95
+ end
96
+ end
97
+
98
+ # update values
99
+ new_row_ptr[i+1] += 1
100
+ new_val[current_column] = val[index]
101
+ new_col_ind[current_column] = current_row-1
102
+ current_column += 1
103
+ end
104
+ end
82
105
 
106
+ # fill in row_ptr
107
+ for i in 1..self.rows-1
108
+ self.row_ptr[i] = new_row_ptr[i] + new_row_ptr[i-1]
109
+ end
110
+
111
+ @col_ind = new_col_ind
112
+ @val = new_val
113
+ end # transpose
114
+
115
+ Contract C::None => C::ArrayOf[C::Num]
83
116
  def t()
84
- self.transpose()
85
- end
117
+ is_invariant?
118
+ # transpose the matrix
119
+ # post array of decomposed matrix values
120
+ self.transpose()
121
+ end # t
86
122
 
123
+ Contract C::Num => C::ArrayOf[C::Num]
87
124
  def matrix_vector(vector)
88
125
  # dev based on http://www.mathcs.emory.edu/~cheung/Courses/561/Syllabus/3-C/sparse.html
126
+ # multiplies the matrix by a vector value (in array form)
127
+ is_invariant?
89
128
  result = Array.new(vector.length, 0)
90
129
  i = 0
91
130
  while i < vector.length do
@@ -97,13 +136,15 @@ module CsrMatrix
97
136
  i += 1
98
137
  end
99
138
  return result
100
- end
139
+ end # matrix_vector
101
140
 
102
141
  # dev based on http://stackoverflow.com/questions/29598299/csr-matrix-matrix-multiplication
103
- # multiply dense (non-dense) matrix to csr matrix [eg. [1, 2]] x 2d array
104
- # key: the dense matrix is LEFT SIDE, the csr matrix is RIGHT SIDE
142
+ Contract C::ArrayOf[C::ArrayOf[C::Num]] => C::ArrayOf[C::ArrayOf[C::Num]]
105
143
  def matrix_multiply(matrix)
106
- # matrix order, assumes both matrices are square
144
+ # multiply dense (non-dense) matrix to csr matrix [eg. [1, 2]] x 2d array
145
+ is_invariant?
146
+ # pre matrix to multiply, existing matrix (matrix.not_null?)
147
+ # post array holding resulting matrix
107
148
  res = Array.new(max_row(matrix)) { Array.new(@columns, 0) } # first denotes row, second denotes columns
108
149
  n = matrix.length
109
150
  i = 0
@@ -128,114 +169,169 @@ module CsrMatrix
128
169
  i += 1
129
170
  end
130
171
  return res
131
- end
172
+ end # matrix_multiply
132
173
 
133
- # multiply two csr together - ref: http://www.mcs.anl.gov/papers/P5007-0813_1.pdf
174
+ Contract MContracts::TwoDMatrixType => C::ArrayOf[C::ArrayOf[C::Num]]
134
175
  def multiply_csr(matrix)
176
+ # multiply two csr together - ref: http://www.mcs.anl.gov/papers/P5007-0813_1.pdf
177
+ is_invariant?
135
178
  return matrix.matrix_multiply(self.decompose())
136
- end
179
+ end # multiply_csr
137
180
 
138
- # helper function to determine deim count is equal
181
+ Contract MContracts::TwoDMatrixType => C::Bool
139
182
  def is_same_dim(matrix)
183
+ # helper function to determine dim count is equal
184
+ is_invariant?
140
185
  return self.dimensions() == matrix.dimensions()
141
- end
186
+ end # is_same_dim
142
187
 
188
+ Contract MContracts::TwoDMatrixType => C::ArrayOf[C::ArrayOf[C::Num]]
143
189
  def matrix_add(matrix)
144
- if self.is_same_dim(matrix)
145
- res = Array.new(@rows) { Array.new(@columns, 0) }
146
- row_idx = 0
147
- cnta = 0 # total logged entries for matrix a
148
- cntb = 0
149
- while row_idx < @rows # eg. 0 1 2
150
- rowa = @row_ptr[row_idx + 1] # eg. 0 2 4 7
151
- rowb = matrix.row_ptr[row_idx + 1]
152
- while cnta < rowa
153
- # keep adding values to res until they're equal
154
- res[row_idx][@col_ind[cnta]] += @val[cnta]
155
- cnta += 1;
156
- end
157
- while cntb < rowb
158
- res[row_idx][@col_ind[cntb]] += matrix.val[cntb]
159
- cntb += 1;
160
- end
161
- row_idx += 1;
162
- end
163
- return res
164
- end
165
- raise Exceptions::MatrixDimException.new, "Matrix does not have same dimensions; cannot add."
166
- return false
167
- end
190
+ # adds a matrix to existing matrix
191
+ is_invariant?
192
+ if !self.is_same_dim(matrix)
193
+ raise Exceptions::MatrixDimException.new, "Matrix does not have same dimensions; cannot add."
194
+ return false
195
+ end
168
196
 
169
- def matrix_subtract(matrix)
170
- if self.is_same_dim(matrix)
171
- res = Array.new(@rows) { Array.new(@columns, 0) }
172
- row_idx = 0
173
- cnta = 0 # total logged entries for matrix a
174
- cntb = 0
175
- while row_idx < @rows # eg. 0 1 2
176
- rowa = @row_ptr[row_idx + 1] # eg. 0 2 4 7
177
- rowb = matrix.row_ptr[row_idx + 1]
178
- while cnta < rowa
179
- # keep adding values to res until they're equal
180
- res[row_idx][@col_ind[cnta]] += @val[cnta]
181
- cnta += 1;
182
- end
183
- while cntb < rowb
184
- res[row_idx][@col_ind[cntb]] -= matrix.val[cntb]
185
- cntb += 1;
186
- end
187
- row_idx += 1;
197
+ res = Array.new(@rows) { Array.new(@columns, 0) }
198
+ row_idx = 0
199
+ cnta = 0 # total logged entries for matrix a
200
+ cntb = 0
201
+ while row_idx < @rows # eg. 0 1 2
202
+ rowa = @row_ptr[row_idx + 1] # eg. 0 2 4 7
203
+ rowb = matrix.row_ptr[row_idx + 1]
204
+ while cnta < rowa
205
+ # keep adding values to res until they're equal
206
+ res[row_idx][@col_ind[cnta]] += @val[cnta]
207
+ cnta += 1;
188
208
  end
189
- return res
190
- end
191
- raise Exceptions::MatrixDimException.new, "Matrix does not have same dimensions; cannot subtract."
192
- return false
193
- end
209
+ while cntb < rowb
210
+ res[row_idx][@col_ind[cntb]] += matrix.val[cntb]
211
+ cntb += 1;
212
+ end
213
+ row_idx += 1;
214
+ end
215
+ return res
216
+ end # matrix_add
194
217
 
195
- # multiply y by x^-1; y * x^-1
196
- # FIXME: Possibly consider rewording for context:
197
- def matrix_left_division(matrix)
198
- if !matrix.is_a?(TwoDMatrix)
199
- raise Exceptions::MatrixTypeException.new, "Matrix is not usable type."
218
+ Contract MContracts::TwoDMatrixType => C::ArrayOf[C::ArrayOf[C::Num]]
219
+ def matrix_subtract(matrix)
220
+ # subtracts a matrix to existing matrix
221
+ is_invariant?
222
+ if !self.is_same_dim(matrix)
223
+ raise Exceptions::MatrixDimException.new, "Matrix does not have same dimensions; cannot subtract."
200
224
  return false
201
225
  end
226
+
227
+ res = Array.new(@rows) { Array.new(@columns, 0) }
228
+ row_idx = 0
229
+ cnta = 0 # total logged entries for matrix a
230
+ cntb = 0
231
+ while row_idx < @rows # eg. 0 1 2
232
+ rowa = @row_ptr[row_idx + 1] # eg. 0 2 4 7
233
+ rowb = matrix.row_ptr[row_idx + 1]
234
+ while cnta < rowa
235
+ # keep adding values to res until they're equal
236
+ res[row_idx][@col_ind[cnta]] += @val[cnta]
237
+ cnta += 1;
238
+ end
239
+ while cntb < rowb
240
+ res[row_idx][@col_ind[cntb]] -= matrix.val[cntb]
241
+ cntb += 1;
242
+ end
243
+ row_idx += 1;
244
+ end
245
+ return res
246
+ end # matrix_subtract
247
+
248
+ Contract MContracts::TwoDMatrixType => C::ArrayOf[C::ArrayOf[C::Num]]
249
+ def multiply_inverse(matrix)
250
+ # divides (multiply by the inverse of ) a matrix to existing matrix
251
+ # sets y * x^-1, where x is your matrix and y is the accepted matrix
252
+ is_invariant?
202
253
  if !matrix.square? || !self.square?
203
254
  raise Exceptions::MatrixDimException.new, "Matrices does not have usable dimensions; cannot divide."
204
255
  return false
205
256
  end
257
+
206
258
  tmpmatrix = TwoDMatrix.new
207
259
  tmpmatrix = matrix
208
260
  tmpmatrix.inverse()
209
261
  return self.multiply_csr(tmpmatrix)
210
- end
262
+ end # matrix_inverse
211
263
 
212
264
  # multiply x by y^-1; x * y^-1
213
- # FIXME: Possibly consider rewording for context: not doing x / y; doing x * y^-1
214
- def matrix_right_division(matrix)
215
- if !matrix.is_a?(TwoDMatrix)
216
- raise Exceptions::MatrixTypeException.new, "Matrix is not usable type."
217
- return false
218
- end
265
+ Contract MContracts::TwoDMatrixType => C::ArrayOf[C::ArrayOf[C::Num]]
266
+ def inverse_multiply(matrix)
267
+ # divides (multiply by the inverse of ) a matrix to existing matrix
268
+ # sets x * y^-1, where x is your matrix and y is the accepted matrix
269
+ is_invariant?
219
270
  if !matrix.square? || !self.square?
220
271
  raise Exceptions::MatrixDimException.new, "Matrices does not have usable dimensions; cannot divide."
221
272
  return false
222
273
  end
274
+
223
275
  tmpmatrix = TwoDMatrix.new
224
276
  tmpmatrix = self
225
277
  tmpmatrix.inverse()
226
278
  return matrix.multiply_csr(tmpmatrix)
279
+ end # inverse_multiply
280
+
281
+ Contract C::None => C::Num
282
+ def count_in_dim()
283
+ is_invariant?
284
+ # helper function, identifies the number of expected values in matrix
285
+ # eg. 2x2 matrix returns 4 values
286
+ return self.rows * self.columns
227
287
  end
228
288
 
229
- # Identifies the 'row' value of an array (eg. the number of entries in a row)
230
- # Helper function, will clean after.
289
+ Contract MContracts::TwoDMatrixType => C::ArrayOf[C::ArrayOf[C::Num]]
290
+ def matrix_division(matrix)
291
+ # linear division of one matrix to the next
292
+ is_invariant?
293
+ if matrix.val.count() != matrix.count_in_dim()
294
+ raise Exceptions::DivideByZeroException.new, "Calculations return divide by zero error."
295
+ return false
296
+ end
297
+ if !self.is_same_dim(matrix)
298
+ raise Exceptions::MatrixDimException.new, "Matrix does not have same dimensions; cannot add."
299
+ return false
300
+ end
301
+
302
+ res = Array.new(@rows) { Array.new(@columns, 0) }
303
+ row_idx = 0
304
+ cnta = 0 # total logged entries for matrix a
305
+ cntb = 0
306
+ while row_idx < @rows # eg. 0 1 2
307
+ rowa = @row_ptr[row_idx + 1] # eg. 0 2 4 7
308
+ rowb = matrix.row_ptr[row_idx + 1]
309
+ while cnta < rowa
310
+ # keep adding values to res until they're equal
311
+ res[row_idx][@col_ind[cnta]] += @val[cnta]
312
+ cnta += 1;
313
+ end
314
+ while cntb < rowb
315
+ res[row_idx][@col_ind[cntb]] = res[row_idx][@col_ind[cntb]].to_f / matrix.val[cntb]
316
+ cntb += 1;
317
+ end
318
+ row_idx += 1;
319
+ end
320
+ return res
321
+ end # matrix_division
322
+
323
+ Contract C::ArrayOf[C::Num] => C::Nat
231
324
  def max_row(array)
325
+ # Identifies the 'row' value of an array (eg. the number of entries in a row)
326
+ is_invariant?
327
+
232
328
  values = array
233
329
  max_count = 0
234
330
  values.each_index do |i|
235
331
  max_count += 1
236
332
  end
237
333
  return max_count
238
- end
334
+ end # max_row
239
335
 
240
- end
241
- end
336
+ end # Arithmetic
337
+ end # CsrMatrix
@@ -1,22 +1,24 @@
1
1
  module CsrMatrix
2
- module Decompositions
2
+ module Decompositions
3
+ include Contracts::Core
4
+ C = Contracts
3
5
 
4
- def eigen()
5
- eigensystem()
6
- end
7
-
8
- def eigensystem()
9
- m = Matrix.rows(self.decompose)
10
- return m.eigensystem().to_a[0].to_a
11
- end
12
-
13
- def lup()
14
- puts "lup"
15
- end
16
-
17
- def lup_decomposition()
18
-
19
- end
20
-
21
- end
22
- end
6
+ Contract C::None => C::ArrayOf[C::ArrayOf[C::Num]]
7
+ def eigen()
8
+ # alias for eigensystem
9
+ # returns a list in the form {eigenvalues, eigenvectors}
10
+ is_invariant?
11
+
12
+ self.eigenvalue()
13
+ end # eigen
14
+
15
+ Contract C::None => C::ArrayOf[C::ArrayOf[C::Num]]
16
+ def eigenvalue()
17
+ # identifies the eigenvalues of a matrix
18
+ is_invariant?
19
+ # post eigenvalues of the matrix
20
+ m = Matrix.rows(self.decompose)
21
+ return m.eigensystem().to_a[1].round().to_a
22
+ end # eigenvalue
23
+ end # Decompositions
24
+ end # CsrMatrix
@@ -1,11 +1,24 @@
1
1
  module CsrMatrix
2
2
  module Exceptions
3
- class NullMatrixException < StandardError; end
3
+ # Occurs when user enters a null matrix for processing.
4
+ class NullMatrixException < StandardError; end
5
+
6
+ # Occurs when a sparse matrix operation occurs wherein its dimensions result in the operation being unavailable.
4
7
  class MatrixDimException < StandardError; end
5
- class ArithmeticException < StandardError; end
6
- class MatrixTypeException < StandardError; end
8
+
9
+ # Occurs when the matrix builder expects a specific type; and is provided the wrong type to generate the sparse matrix.
10
+ class MatrixTypeException < StandardError; end
11
+
12
+ # Occurs when the system divides by 0; standard arithmetic error.
7
13
  class DivideByZeroException < StandardError; end
14
+
15
+ # Occurs when index queried is out of range of the matrix.
8
16
  class IndexOutOfRangeException < StandardError; end
17
+
18
+ # Occurs when the sparse matrix is used in processing against a null / nil value.
9
19
  class ArgumentNullException < StandardError; end
10
- end
11
- end
20
+
21
+ #
22
+ class InvariantError < StandardError; end
23
+ end # exceptions
24
+ end # csrmatrix