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 +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +106 -1
- data/csrmatrix-1.0.0.gem +0 -0
- data/lib/csrmatrix/arithmetic.rb +213 -117
- data/lib/csrmatrix/decompositions.rb +22 -20
- data/lib/csrmatrix/exceptions.rb +18 -5
- data/lib/csrmatrix/functions.rb +52 -16
- data/lib/csrmatrix/helpers.rb +23 -11
- data/lib/csrmatrix/mcontracts.rb +9 -0
- data/lib/csrmatrix/operations.rb +60 -18
- data/lib/csrmatrix/properties.rb +219 -96
- data/lib/csrmatrix/version.rb +1 -1
- data/lib/csrmatrix.rb +204 -94
- metadata +4 -2
data/lib/csrmatrix/functions.rb
CHANGED
@@ -1,33 +1,69 @@
|
|
1
1
|
module CsrMatrix
|
2
2
|
module Functions
|
3
|
-
|
3
|
+
include Contracts::Core
|
4
|
+
include Contracts::Builtin
|
5
|
+
C = Contracts
|
6
|
+
|
7
|
+
def self.included(exceptions)
|
8
|
+
exceptions.send :include, Exceptions
|
9
|
+
end
|
10
|
+
|
11
|
+
Contract C::None => C::Num
|
4
12
|
def determinant()
|
13
|
+
# identifies the determinant of a matrix
|
14
|
+
is_invariant?
|
15
|
+
if !self.square?()
|
16
|
+
raise Exceptions::MatrixDimException.new, "Matrix is not square."
|
17
|
+
return false
|
18
|
+
end
|
19
|
+
|
5
20
|
m = Matrix.rows(self.decompose)
|
6
|
-
m.det()
|
7
|
-
end
|
21
|
+
return m.det()
|
22
|
+
end # determinant
|
8
23
|
|
24
|
+
Contract C::None => C::Num
|
9
25
|
def det()
|
10
|
-
|
11
|
-
|
26
|
+
# alias for determinant
|
27
|
+
# identifies the determinant of a matrix
|
28
|
+
is_invariant?
|
29
|
+
return self.determinant()
|
30
|
+
end # det
|
12
31
|
|
32
|
+
Contract C::None => C::Num
|
13
33
|
def rank()
|
34
|
+
# identifies the rank of a matrix
|
35
|
+
is_invariant?
|
14
36
|
m = Matrix.rows(self.decompose)
|
15
|
-
m.rank()
|
16
|
-
end
|
37
|
+
return m.rank()
|
38
|
+
end # rank
|
17
39
|
|
40
|
+
#FIXME: I'm not sure whats going on here?
|
18
41
|
def round(ndig = 0)
|
19
|
-
|
20
|
-
|
21
|
-
|
42
|
+
# identifies the round of a matrix (that is, each value rounded by a specific degree)
|
43
|
+
# pre integer of degree, existing matrix (matrix.not_null?)
|
44
|
+
is_invariant?
|
45
|
+
# post rounded array
|
46
|
+
for i in 0..self.val.count-1
|
47
|
+
self.val[i] = self.val[i].round(ndig)
|
48
|
+
end
|
49
|
+
self.val
|
50
|
+
end # round
|
22
51
|
|
52
|
+
Contract C::None => Contracts::Num
|
23
53
|
def trace()
|
54
|
+
# identifies the trace of the matrix
|
55
|
+
is_invariant?
|
24
56
|
m = Matrix.rows(self.decompose)
|
25
|
-
m.trace()
|
26
|
-
end
|
57
|
+
return m.trace()
|
58
|
+
end # trace
|
27
59
|
|
60
|
+
Contract C::None => Contracts::Num
|
28
61
|
def tr()
|
29
|
-
|
30
|
-
|
62
|
+
# alias for trace
|
63
|
+
# identifies the trace of the matrix
|
64
|
+
is_invariant?
|
65
|
+
return self.trace()
|
66
|
+
end # tr
|
31
67
|
|
32
|
-
end
|
33
|
-
end
|
68
|
+
end # Functions
|
69
|
+
end # CsrMatrix
|
data/lib/csrmatrix/helpers.rb
CHANGED
@@ -6,8 +6,10 @@ module CsrMatrix
|
|
6
6
|
# for pre-processing of matrix
|
7
7
|
#
|
8
8
|
|
9
|
-
# Identifies the 'column' value of an array (eg. the number of entries in a column)
|
10
9
|
def max_col(array)
|
10
|
+
# Identifies the 'column' value of an array (eg. the number of entries in a column)
|
11
|
+
# pre array
|
12
|
+
# post column count of array
|
11
13
|
values = array
|
12
14
|
max_count = 0
|
13
15
|
# Loop over indexes.
|
@@ -23,19 +25,24 @@ module CsrMatrix
|
|
23
25
|
end
|
24
26
|
end
|
25
27
|
return max_count
|
26
|
-
end
|
28
|
+
end # max_col
|
27
29
|
|
28
|
-
# Identifies the 'row' value of an array (eg. the number of entries in a row)
|
29
30
|
def max_row(array)
|
31
|
+
# Identifies the 'row' value of an array (eg. the number of entries in a row)
|
32
|
+
# pre array
|
33
|
+
# post row count of array
|
30
34
|
values = array
|
31
35
|
max_count = 0
|
32
36
|
values.each_index do |i|
|
33
37
|
max_count += 1
|
34
38
|
end
|
35
39
|
return max_count
|
36
|
-
end
|
40
|
+
end # max_row
|
37
41
|
|
38
42
|
def count_nonzero(array)
|
43
|
+
# Finds all nonzero values in an array.
|
44
|
+
# pre array
|
45
|
+
# post int nonzero count of array
|
39
46
|
max_count = 0
|
40
47
|
array.each_index do |i|
|
41
48
|
subarray = array[i]
|
@@ -46,10 +53,13 @@ module CsrMatrix
|
|
46
53
|
end
|
47
54
|
end
|
48
55
|
return max_count
|
49
|
-
end
|
56
|
+
end # count_nonzero
|
50
57
|
|
51
|
-
# Code taken from http://stackoverflow.com/questions/9545613/getting-dimension-of-multidimensional-array-in-ruby
|
52
58
|
def depth(array)
|
59
|
+
# Code from http://stackoverflow.com/questions/9545613/getting-dimension-of-multidimensional-array-in-ruby
|
60
|
+
# Identifies the depth of an array.
|
61
|
+
# pre array
|
62
|
+
# post int depth of array
|
53
63
|
return 0 if array.class != Array
|
54
64
|
result = 1
|
55
65
|
array.each do |sub_a|
|
@@ -59,10 +69,12 @@ module CsrMatrix
|
|
59
69
|
end
|
60
70
|
end
|
61
71
|
return result
|
62
|
-
end
|
72
|
+
end # depth
|
63
73
|
|
64
|
-
# Counts all elements in array - assumed 2d
|
65
74
|
def count_total(array)
|
75
|
+
# Counts all elements in array - assumed 2d
|
76
|
+
# pre array
|
77
|
+
# post int count of all elements
|
66
78
|
max_count = 0
|
67
79
|
array.each_index do |i|
|
68
80
|
subarray = array[i]
|
@@ -71,7 +83,7 @@ module CsrMatrix
|
|
71
83
|
end
|
72
84
|
end
|
73
85
|
return max_count
|
74
|
-
end
|
86
|
+
end # count_total
|
75
87
|
|
76
|
-
end
|
77
|
-
end
|
88
|
+
end # Helpers
|
89
|
+
end # CsrMatrix
|
data/lib/csrmatrix/operations.rb
CHANGED
@@ -1,33 +1,75 @@
|
|
1
|
+
require "csrmatrix/exceptions"
|
2
|
+
|
1
3
|
module CsrMatrix
|
2
4
|
module Operations
|
5
|
+
include Contracts::Core
|
6
|
+
C = Contracts
|
7
|
+
|
8
|
+
Contract C::Nat => C::Num
|
3
9
|
def get_value(index)
|
10
|
+
# gets the value off of the index of matrix
|
11
|
+
is_invariant?
|
4
12
|
return @val[index]
|
5
|
-
end
|
13
|
+
end # get_value
|
14
|
+
|
15
|
+
Contract C::Nat, C::Or[C::Nat, nil] => C::Num
|
16
|
+
def index(row, col=nil)
|
17
|
+
# gets the index in the matrix at row, col
|
18
|
+
is_invariant?
|
19
|
+
|
20
|
+
if col == nil
|
21
|
+
if @val.count < row
|
22
|
+
raise CsrMatrix::Exceptions::IndexOutOfRangeException.new, "Index out of Bounds"
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
|
26
|
+
return @val[row-1]
|
27
|
+
else
|
28
|
+
if !checkInputBounds(row, col)
|
29
|
+
raise CsrMatrix::Exceptions::IndexOutOfRangeException.new, "Index out of Bounds"
|
30
|
+
return false
|
31
|
+
end
|
6
32
|
|
33
|
+
num_elm_in_prev = row_ptr[row-1]
|
34
|
+
num_elm_in_row = row_ptr[row] - num_elm_in_prev
|
35
|
+
|
36
|
+
(0...num_elm_in_row).each do | x |
|
37
|
+
if ( col-1 == @col_ind[num_elm_in_prev+x] )
|
38
|
+
return @val[num_elm_in_prev+x]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
return 0
|
42
|
+
end
|
43
|
+
end # index
|
44
|
+
|
45
|
+
Contract C::None => C::Any
|
7
46
|
def print_full()
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
47
|
+
# prints the full matrix for user
|
48
|
+
is_invariant?
|
49
|
+
full_matrix = self.decompose()
|
50
|
+
full_matrix.each do | row |
|
51
|
+
row.each do | val |
|
52
|
+
print "#{val} "
|
15
53
|
end
|
16
54
|
puts ""
|
17
|
-
end
|
18
|
-
end
|
55
|
+
end
|
56
|
+
end # print_full
|
19
57
|
|
58
|
+
Contract C::None => C::Any
|
20
59
|
def print_sparse()
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
60
|
+
# prints all nonzero values of matrix for user
|
61
|
+
is_invariant?
|
62
|
+
full_matrix = self.decompose()
|
63
|
+
full_matrix.each do | row |
|
64
|
+
row.each do | val |
|
65
|
+
if val == 0
|
66
|
+
print "---"
|
25
67
|
else
|
26
|
-
print "
|
68
|
+
print " #{val} "
|
27
69
|
end
|
28
70
|
end
|
29
71
|
puts ""
|
30
72
|
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
73
|
+
end # print_sparse
|
74
|
+
end # Operations
|
75
|
+
end # CsrMatrix
|
data/lib/csrmatrix/properties.rb
CHANGED
@@ -1,98 +1,221 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
def self.included(exceptions)
|
5
|
-
exceptions.send :include, Exceptions
|
6
|
-
end
|
7
|
-
|
8
|
-
# Determines if the matrix is diagonal; wherein the values outside the main diagonal are all zero.
|
9
|
-
def diagonal?
|
10
|
-
m = Matrix.rows(self.decompose)
|
11
|
-
return m.diagonal?
|
12
|
-
end
|
13
|
-
|
14
|
-
# Determines if the matrix is empty; wherein all the values are zero.
|
15
|
-
def empty?
|
16
|
-
m = Matrix.rows(self.decompose)
|
17
|
-
return m.empty?
|
18
|
-
end
|
19
|
-
|
20
|
-
# Determine if the matrix is hermitian.
|
21
|
-
def hermitian?
|
22
|
-
m = Matrix.rows(self.decompose)
|
23
|
-
return m.hermitian?
|
24
|
-
end
|
25
|
-
|
26
|
-
# Determines if the matrix is lower-diagonal; wherein all the values only exist on and below the diagonal line.
|
27
|
-
def lower_triangular?
|
28
|
-
m = Matrix.rows(self.decompose)
|
29
|
-
return m.lower_triangular?
|
30
|
-
end
|
31
|
-
|
32
|
-
# Determines if the matrix is normal; wherein if the number of rows or columns is 0
|
33
|
-
def normal?
|
34
|
-
m = Matrix.rows(self.decompose)
|
35
|
-
return m.normal?
|
36
|
-
end
|
37
|
-
|
38
|
-
# Determines if the matrix is orthogonal; wherein the rows and columns are orthogonal unit vectors.
|
39
|
-
def orthogonal?
|
40
|
-
m = Matrix.rows(self.decompose)
|
41
|
-
return m.orthogonal?
|
42
|
-
end
|
43
|
-
|
44
|
-
# Determines if the matrix is a permutation; wherein it is an nxn version of the identity matrix.
|
45
|
-
def permutation?
|
46
|
-
m = Matrix.rows(self.decompose)
|
47
|
-
return m.permutation?
|
48
|
-
end
|
49
|
-
|
50
|
-
# Determines if the matrix is real; wherein the matrix consists entirely of real numbers.
|
51
|
-
def real?
|
52
|
-
m = Matrix.rows(self.decompose)
|
53
|
-
return m.real?
|
54
|
-
end
|
55
|
-
|
56
|
-
# Determines if the matrix is nonsingular
|
57
|
-
def nonsingular?
|
58
|
-
return !self.singular?
|
59
|
-
end
|
60
|
-
|
61
|
-
# Determines if the matrix is singular
|
62
|
-
def singular?
|
63
|
-
m = Matrix.rows(self.decompose)
|
64
|
-
return m.singular?
|
65
|
-
end
|
66
|
-
|
67
|
-
# Determines if the matrix is square
|
68
|
-
def square?
|
69
|
-
m = Matrix.rows(self.decompose)
|
70
|
-
return m.square?
|
71
|
-
end
|
72
|
-
|
73
|
-
# Determines if the matrix is symmetric
|
74
|
-
def symmetric?
|
75
|
-
m = Matrix.rows(self.decompose)
|
76
|
-
return m.symmetric?
|
77
|
-
end
|
78
|
-
|
79
|
-
# Determines if the matrix is unitary
|
80
|
-
def unitary?
|
81
|
-
m = Matrix.rows(self.decompose)
|
82
|
-
return m.unitary?
|
83
|
-
end
|
84
|
-
|
85
|
-
# Determines if the matrix is upper-triangular
|
86
|
-
def upper_triangular?
|
87
|
-
m = Matrix.rows(self.decompose)
|
88
|
-
return m.upper_triangular?
|
89
|
-
end
|
90
|
-
|
91
|
-
# Determines if the matrix is zero
|
92
|
-
def zero?
|
93
|
-
m = Matrix.rows(self.decompose)
|
94
|
-
return m.zero?
|
95
|
-
end
|
1
|
+
require "matrix"
|
2
|
+
require "csrmatrix/exceptions"
|
3
|
+
require "contracts"
|
96
4
|
|
5
|
+
module CsrMatrix
|
6
|
+
module Properties
|
7
|
+
include Contracts::Core
|
8
|
+
C = Contracts
|
9
|
+
|
10
|
+
def self.included(exceptions)
|
11
|
+
exceptions.send :include, Exceptions
|
12
|
+
end
|
13
|
+
|
14
|
+
Contract C::None => C::Bool
|
15
|
+
def diagonal?
|
16
|
+
# Determines if the matrix is diagonal; wherein the values outside the main diagonal are all zero.
|
17
|
+
is_invariant?
|
18
|
+
for i in 0..self.columns-1
|
19
|
+
if (self.col_ind[i] != i) || (self.row_ptr[i] != i)
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
return true
|
24
|
+
end # diagonal?
|
25
|
+
|
26
|
+
Contract C::None => C::Bool
|
27
|
+
def empty?
|
28
|
+
# Determines if the matrix is empty; wherein all the values are zero.
|
29
|
+
is_invariant?
|
30
|
+
if self.val.count() == 0
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
return false
|
34
|
+
end # empty?
|
35
|
+
|
36
|
+
Contract C::None => C::Bool
|
37
|
+
def lower_triangular?
|
38
|
+
# Determines if the matrix is lower-diagonal; wherein all the values only exist on and below the diagonal line.
|
39
|
+
is_invariant?
|
40
|
+
for i in 0..self.columns-1
|
41
|
+
for column_index in row_ptr[i]..row_ptr[i+1]-1
|
42
|
+
if (self.col_ind[column_index] > i)
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
return true
|
48
|
+
end # lower_triangular?
|
49
|
+
|
50
|
+
#USES COMPLEX MATRIX
|
51
|
+
Contract C::None => C::Bool
|
52
|
+
def normal?
|
53
|
+
# Determines if the matrix is normal
|
54
|
+
is_invariant?
|
55
|
+
if !self.square?
|
56
|
+
raise Exceptions::MatrixDimException.new, "Matrix is not square."
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
|
60
|
+
m = Matrix.rows(self.decompose)
|
61
|
+
return m.normal?
|
62
|
+
end # normal?
|
63
|
+
|
64
|
+
Contract C::None => C::Bool
|
65
|
+
def orthogonal?
|
66
|
+
# Determines if the matrix is orthogonal; wherein the rows and columns are orthogonal unit vectors.
|
67
|
+
is_invariant?
|
68
|
+
if !self.square?
|
69
|
+
raise Exceptions::MatrixDimException.new, "Matrix is not square."
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
|
73
|
+
# transpose the existing matrix
|
74
|
+
@matrix_transpose = TwoDMatrix.new
|
75
|
+
@matrix_transpose.build_from_csr(self.row_ptr, self.col_ind, self.val, self.columns, self.rows)
|
76
|
+
@matrix_transpose.transpose()
|
77
|
+
|
78
|
+
# build an orthogonal matrix
|
79
|
+
@matrix_orthogonal = TwoDMatrix.new
|
80
|
+
@matrix_orthogonal.build_from_array(self.multiply_csr(@matrix_transpose))
|
81
|
+
|
82
|
+
# test the values in the orthogonal matrix
|
83
|
+
for i in 0..@matrix_orthogonal.val.count()-1
|
84
|
+
if @matrix_orthogonal.val[i] != 1
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
end
|
88
|
+
return true
|
89
|
+
end # orthogonal?
|
90
|
+
|
91
|
+
Contract C::None => C::Bool
|
92
|
+
def permutation?
|
93
|
+
# Determines if the matrix is a permutation; wherein it is an nxn version of the identity matrix.
|
94
|
+
is_invariant?
|
95
|
+
if !self.square?
|
96
|
+
raise Exceptions::MatrixDimException.new, "Matrix is not square."
|
97
|
+
return false
|
98
|
+
end
|
99
|
+
|
100
|
+
#Check the proper number of values
|
101
|
+
if self.val.length != self.columns
|
102
|
+
return false
|
103
|
+
end
|
104
|
+
|
105
|
+
#check for the proper values. ie only 1's
|
106
|
+
for value in self.val
|
107
|
+
if value != 1
|
108
|
+
return false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
column_ind = self.col_ind
|
113
|
+
for column_index in self.col_ind
|
114
|
+
if column_ind.include?(column_index)
|
115
|
+
column_ind.remove(column_index)
|
116
|
+
else
|
117
|
+
return false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end # permutation?
|
121
|
+
|
122
|
+
Contract C::None => C::Bool
|
123
|
+
def real?
|
124
|
+
# Determines if the matrix is real; wherein the matrix consists entirely of real numbers.
|
125
|
+
is_invariant?
|
126
|
+
for value in self.val
|
127
|
+
if !value.is_a? Numeric
|
128
|
+
return false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
return true
|
132
|
+
end # real?
|
133
|
+
|
134
|
+
Contract C::None => C::Bool
|
135
|
+
def not_null?
|
136
|
+
if @val == nil
|
137
|
+
return false
|
138
|
+
end
|
139
|
+
return true
|
97
140
|
end
|
98
|
-
|
141
|
+
|
142
|
+
Contract C::None => C::Bool
|
143
|
+
def nonsingular?
|
144
|
+
# Determines if the matrix is nonsingular ; simply the inverse of the singular function
|
145
|
+
is_invariant?
|
146
|
+
return !self.singular?
|
147
|
+
end # nonsingular?
|
148
|
+
|
149
|
+
Contract C::None => C::Bool
|
150
|
+
def singular?
|
151
|
+
# Determines if the matrix is singular
|
152
|
+
is_invariant?
|
153
|
+
if self.determinant != 0
|
154
|
+
return false
|
155
|
+
end
|
156
|
+
return true
|
157
|
+
end # singular?
|
158
|
+
|
159
|
+
Contract C::None => C::Bool
|
160
|
+
def symmetric?
|
161
|
+
# Determines if the matrix is symmetric
|
162
|
+
is_invariant?
|
163
|
+
if !self.square?
|
164
|
+
raise Exceptions::MatrixDimException.new, "Matrix is not square."
|
165
|
+
return false
|
166
|
+
end
|
167
|
+
|
168
|
+
# transpose the existing matrix
|
169
|
+
@matrix_transpose = TwoDMatrix.new
|
170
|
+
@matrix_transpose.build_from_csr(self.row_ptr, self.col_ind, self.val, self.columns, self.rows)
|
171
|
+
@matrix_transpose.transpose()
|
172
|
+
|
173
|
+
for i in 0..self.val.count()-1
|
174
|
+
if self.val[i] != @matrix_transpose.val[i]
|
175
|
+
return false
|
176
|
+
end
|
177
|
+
end
|
178
|
+
return true
|
179
|
+
end # symmetric?
|
180
|
+
|
181
|
+
#USES COMPLEX MATRIX
|
182
|
+
Contract C::None => C::Bool
|
183
|
+
def unitary?
|
184
|
+
# Determines if the matrix is unitary
|
185
|
+
is_invariant?
|
186
|
+
if !self.square?
|
187
|
+
raise Exceptions::MatrixDimException.new, "Matrix is not square."
|
188
|
+
return false
|
189
|
+
end
|
190
|
+
m = Matrix.rows(self.decompose)
|
191
|
+
return m.unitary?
|
192
|
+
end # unitary?
|
193
|
+
|
194
|
+
Contract C::None => C::Bool
|
195
|
+
def upper_triangular?
|
196
|
+
# Determines if the matrix is upper-triangular
|
197
|
+
is_invariant?
|
198
|
+
for i in 0..self.columns-1
|
199
|
+
for column_index in row_ptr[i]..row_ptr[i+1]-1
|
200
|
+
if (self.col_ind[column_index] < i)
|
201
|
+
return false
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
return true
|
206
|
+
end # upper triangular?
|
207
|
+
|
208
|
+
Contract C::None => C::Bool
|
209
|
+
def zero?
|
210
|
+
# Determines if the matrix is zero
|
211
|
+
is_invariant?
|
212
|
+
for value in self.val
|
213
|
+
if value != 0
|
214
|
+
return false
|
215
|
+
end
|
216
|
+
end
|
217
|
+
return true
|
218
|
+
end # zero?
|
219
|
+
|
220
|
+
end # Properties
|
221
|
+
end # CsrMatrix
|
data/lib/csrmatrix/version.rb
CHANGED