lib/csrmatrix.rb in csrmatrix-1.0.0 vs lib/csrmatrix.rb in csrmatrix-1.0.1
- old
+ new
@@ -1,74 +1,137 @@
require "csrmatrix/version"
-require "csrmatrix/properties"
require "csrmatrix/arithmetic"
+require "csrmatrix/properties"
require "csrmatrix/functions"
require "csrmatrix/decompositions"
require "csrmatrix/operations"
require "csrmatrix/helpers"
require "csrmatrix/exceptions"
+require "contracts"
module CsrMatrix
# The current website ref. Used for verificationn of rb systems.
- Url = "https://github.com/Team-Aqua/Matrix-Library/"
-end
+ Url = "https://github.com/Team-Aqua/Matrix-Library/"
+end# CsrMatrix
+
+
# General code convention in this manner - generate documentation via 'rdoc lib'.
class TwoDMatrix
#Need to ensure we include Object Class overwrites.
include CsrMatrix::Operations
include CsrMatrix::Properties
include CsrMatrix::Arithmetic
include CsrMatrix::Functions
include CsrMatrix::Decompositions
include CsrMatrix::Helpers
include CsrMatrix::Exceptions
+ include CsrMatrix::MContracts
+ include Contracts::Core
+ include Contracts::Invariants
+ C = Contracts
+ invariant(@rows) { @rows >= 0}
+ invariant(@columns) { @columns >= 0}
+ invariant(:val) {self.val != nil}
+
# The current website ref. Used for verification of rb systems.
Url = "https://github.com/Team-Aqua/Matrix-Library/"
attr_reader :row_ptr, :col_ind, :val, :rows, :columns, :ndim
# Blank setup; setup module.
- def initialize()
+ def initialize()
+ # invariant
+ # @nonzero_count.is_a?(array) and @nonzero_count.count() >= 0
+ # @row_pointer.is_a?(array) and @row_pointer.count() >= 0
+ # @col_ind.is_a?(array) and @col_ind.count() >= 0
+ # @val.is_a?(array) and @val.count() >= 0
+ # @rows >= 0
+ # @columns >= 0
+ # @dimension == 2
@nonzero_count = nil
@row_ptr = nil
@col_ind = nil
@val = nil
@rows = 0
@columns = 0
@ndim = 2
- end
+ end # initialize
##
# SPARSE MATRIX ATTRIBUTE OPERATORS
# matrix attributes and overloaded operators
#
+ def is_invariant?
+ if @val == nil
+ raise InvariantError.new, "Empty Matrix"
+ return false
+ end
+ return true
+ end
# equals override for matrix operations
def ==(o)
+ # equals overide to check if object o equals self
+ # pre o, self
+ # post true if o is_a csrmatrix and o == self
o.class == self.class && o.state == state
- end
+ end # ==(o)
# FIXME: convert to protected value
+ # Contract C::None => C::ArrayOf[ArrayOf[C::Num],ArrayOf[C::Nat],ArrayOf[C::Nat],C::Nat,C::Nat,C::Nat]
def state
+ # returns the current state of the csrmatrix
+ # pre self
+ # post [@value, @row_pointer, @column_index, @rows, @columns, @dimension]
[@val, @row_ptr, @col_ind, @rows, @columns, @ndim]
- end
+ end # state
# Finds column and row value of an array.
+ Contract C::None => C::ArrayOf[C::Nat]
def dimensions()
+ is_invariant?
+ # returns the dimensions of the csrmatrix
return [@rows, @columns]
- end
+ end # dimensions
+ Contract C::None => C::Bool
def square?
+ # returns whether or not the system is square
+ is_invariant?
return self.rows == self.columns
- end
+ end # square?
+ Contract C::Nat, C::Nat => C::Bool
+ def checkInputBounds(row, col)
+ # checks whether or not the index searched is within bounds
+ if row > @rows
+ raise IndexOutOfRangeException.new, "Row index too large"
+ return false
+ elsif col > @columns
+ raise IndexOutOfRangeException.new, "Column index too large"
+ return false
+ elsif row < 0
+ raise IndexOutOfRangeException.new, "Row index too small"
+ return false
+ elsif col < 0
+ raise IndexOutOfRangeException.new, "Column index too small"
+ return false
+ else
+ return true
+ end
+ end # checkInputBounds
+
##
# MATRIX DECOMPOSITION FUNCTIONS
#
+ Contract C::None => C::ArrayOf[C::ArrayOf[C::Num]]
def decompose()
+ # decompose the matrix into an array
+ # pre csrmatrix
+ # post array from the csrmartix
res = Array.new(@rows) { Array.new(@columns, 0) }
row_counter = 0
row_idx = 0
@row_ptr.drop(1).each do |i| #eg. 2 4 7 10
while row_counter < i
@@ -76,106 +139,45 @@
row_counter += 1
end
row_idx += 1
end
return res
- end
+ end # decompose
+ Contract C::None => Matrix
+ def decomp_to_matrix()
+ @matrix = Matrix.rows(self.decompose())
+ return @matrix
+ end # decomp_to_matrix
+
##
# MATRIX GENERATION FUNCTIONS
# generation of csr matrix
#
# Builds when given a 2d array to CSR
+ Contract C::ArrayOf[C::ArrayOf[C::Num]] => C::Any
def build_from_array(array)
- if array.is_a?(Array)
- if depth(array) == 2
- if same_sublength(array)
- dimensions = convert_to_csr(array)
- @columns = dimensions[0]
- @rows = dimensions[1]
- nonzero_count = dimensions[2] # FIXME: consider removing
- @val = dimensions[3]
- @row_ptr = dimensions[4]
- @col_ind = dimensions[5]
- return true
- end
- raise MatrixDimException.new, "Invalid row/column pairs imported."
- return false
- end
- raise MatrixDimException.new, "Invalid dimensions."
+ #Contracts: Pre
+ if !same_sublength(array)
+ raise MatrixDimException.new, "Invalid row/column pairs imported."
return false
end
- raise MatrixTypeException.new, "Wrong type convert to matrix"
- end
-
- # imports a matrix from a matrix library
- def build_from_matrix(matrix)
- if matrix.is_a?(Matrix)
- build_from_array(matrix.to_a())
- return true
- end
- raise MatrixTypeException.new, "Wrong type convert to matrix."
- end
-
- # builds a matrix given its rows
- def build_from_rows(array)
- build_from_array(array)
- self.transpose()
- end
-
-
- # builds a matrix given its columns ;; redirect to array build
- def build_from_columns(array)
- self.build_from_array(array)
- end
-
- # generates an identity matrix
- def build_identity_matrix(size)
- # FIXME: test code: replace with CSR identity gen
- if size.is_a?(Numeric)
- self.build_from_array(Matrix.identity(size).to_a())
- return true
- end
- raise MatrixTypeException.new, "Wrong type convert to matrix."
- return false
- end
-
- # generates a zero matrix
- def build_zero_matrix(rows, columns = rows)
- # FIXME: test code: replace with CSR zero gen
- if rows.is_a?(Numeric) && columns.is_a?(Numeric)
- self.build_from_array(Matrix.zero(rows, columns).to_a())
- return true
- end
- raise MatrixTypeException.new, "Wrong type convert to matrix."
- return false
- end
-
- # Builds array using user-generated CSR values
- def build_from_csr(row_ptr, col_ind, val, col_siz, row_siz)
- # generate
- @val = val
- @row_ptr = row_ptr
- @col_ind = col_ind
- @rows = row_siz
- @columns = col_siz
- end
-
- # ensures that all subarrays are of same length
- def same_sublength(array)
- testLength = array[0].length
- array.each do |subarray|
- if(subarray.length != testLength)
- return false
- end
- end
+ #END Contracts: Pre
+ @val = [] #Allows Invariant Check to Pass for following method call
+ @columns, @rows, nonzero_count, @val, @row_ptr, @col_ind = convert_to_csr(array)
return true
- end
+ end # build_from_array
- # Finds the column count, row count and non-zero values in one loop.
+ # Finds the column count, row count and non-zero values in one loop.
+ Contract C::ArrayOf[C::ArrayOf[C::Num]] => C::Any
def convert_to_csr(array)
+ # converts a given array to csr format
+ # pre array
+
+
+ # post csrmatrix from array
row_count = 0
col_count = 0
nonzero_count = 0
row_val = 0
@@ -196,10 +198,13 @@
subarray = array[i]
subarray.each_index do |x| # each column entry in row
col_tmp += 1
if array[i][x] != 0
# use nonzero value in CSR
+ if array[i][x] == nil
+ return false
+ end
nonzero_count += 1
value_array << array[i][x]
col_ind << col_val
row_val += 1
end
@@ -210,8 +215,113 @@
end
end
row_prev_sum = row_val
row_ptr << row_prev_sum
return [col_count, row_count, nonzero_count, value_array, row_ptr, col_ind]
- end
+ end # convert_to_csr
-end
+ # builds matrix dependent on input
+ Contract String, C::Or[C::ArrayOf[C::Or[C::ArrayOf[C::Num], C::Num]],C::Nat, Matrix], C::Or[nil, Any, C::None] => C::Bool
+ def build(type, data, extra = nil)
+ # builds matrix dependent on input
+ # pre string type
+ # data, dependent type
+ # post generated matrix
+ # boolean depending on build
+ case type
+ when "matrix"
+ self.build_from_matrix(data)
+ when "row", "rows"
+ self.build_from_rows(data)
+ when "array"
+ self.build_from_array(data)
+ when "column", "columns"
+ self.build_from_columns(data)
+ when "identity", "i", "unit"
+ if extra != nil
+ self.build_identity_matrix(data, extra)
+ else
+ self.build_identity_matrix(data)
+ end
+ when "zero"
+ self.build_zero_matrix(data)
+ when "csr"
+ self.build_from_csr(data[0], data[1], data[2], data[3], data[4])
+ else
+ raise MatrixTypeException.new, "Bad build type, no build response."
+ return false;
+ end
+ return true;
+ end
+
+ # imports a matrix from a matrix library
+ Contract Matrix => C::Bool
+ def build_from_matrix(matrix)
+ # builds a csr matrix a ruby matrix
+ build_from_array(matrix.to_a())
+ return true
+ end # build_from_matrix
+
+ # builds a matrix given its rows
+ Contract C::ArrayOf[C::ArrayOf[C::Num]] => C::ArrayOf[C::Num]
+ def build_from_rows(array)
+ # builds a csr matrix from rows
+ build_from_array(array)
+ self.transpose()
+ end # build_from_rows
+
+
+
+ Contract C::ArrayOf[C::ArrayOf[C::Num]] => C::Bool
+ def build_from_columns(array)
+ # builds a matrix given its columns ;; redirect to array build
+ # build a matrix given columns. same implimentation as array build
+ self.build_from_array(array)
+ end # build_from_columns
+
+ # generates an identity matrix
+ Contract C::Nat => true
+ def build_identity_matrix(size)
+ # FIXME: test code: replace with CSR identity gen
+ # generate identity matrix of a given size
+ self.build_from_array(Matrix.identity(size).to_a())
+ end # build_identity_matrix
+
+ # generates a zero matrix
+ Contract C::Nat, C::Nat => true
+ def build_zero_matrix(rows, columns = rows)
+ # FIXME: test code: replace with CSR zero gen
+ # generate a matrix with all values equaling zero for a given number of rows and columns
+ self.build_from_array(Matrix.zero(rows, columns).to_a())
+ return true
+ end # build_zero_matrix
+
+ # Builds array using user-generated CSR values
+ Contract C::ArrayOf[C::Nat], C::ArrayOf[C::Nat], C::ArrayOf[C::Num], C::Nat, C::Nat => TwoDMatrix
+ def build_from_csr(row_ptr, col_ind, val, col_siz, row_siz)
+ # generate an array from user generated csr values
+ @val = val
+ @row_ptr = row_ptr
+ @col_ind = col_ind
+ @rows = row_siz
+ @columns = col_siz
+ self
+ end # build_from_csr
+
+ # ensures that all subarrays are of same length
+
+ #FIXME: Could be a contract in itself
+ # Contract C::ArrayOf[C::ArrayOf[C::Num]] => C::Bool #Causes Invariant issues
+ def same_sublength(array)
+ # ensures that all sub arrays have the same length
+ testLength = array[0].length
+ array.each do |subarray|
+ if(subarray.length != testLength)
+ return false
+ end
+ end
+ return true
+ end #same_sublength
+
+
+
+end # TwoDMatrix
\ No newline at end of file