dimanche 13 janvier 2008

Matrices en Ruby : 2 - Matrices creuses ?

Petit retour sur les matrices. On avait vu dans le post précédent à ce sujet que la classe Matrix n'interdit pas la création de matrices non-rectangulaires ou creuses.

De façon assez optimiste, je pensais que cela pourrait être utile en particulier pour le traitement de calculs avec matrices creuses, technique régulièrement employée en calcul scientifique pour des questions évidentes d'économie de temps d'exécution et de mémoire. En effet, une cellule vide correspondrait simplement à un 0.0, dont le stockage est inutile. Il suffisait de tester pour voir...

... Et la conclusion est qu'il s'agit ici d'avantage d'un bug que d'une fonctionnalité.

Le code suivant met en évidence le type de problème que l'on peut rencontrer avec une matrice creuse, et propose (hormis la méthode print du post précédent) une petite méthode de "sécurisation" de matrice creuse : secu_sparse.

Le code :



require 'Matrix'
#require 'mathn'#Mandatory for determinant
#calculation with rationnals

class Matrix
# Human readable printing
def print
for i in (0...self.row_size)
strg = ""
for j in (0...self.column_size)
strg = strg + " " + (self.[](i,j)).to_s
end
puts strg
end
end
end

tab = [
[2.2,0.1],
[1.0]
]

mat1 = Matrix.rows tab
puts "Sparse matrix = "
mat1.print

#puts mat1.determinant
#=> error : *nil ?

mat2 = Matrix.zero(2)*0.0
puts "Zero matrix = "
mat2.print

#mat3 = mat2 +mat1
#=> error : +nil ?

class Matrix
def secu_sparse
tab = []
for i in (0...self.row_size)
tab.push []
for j in (0...self.column_size)
tab[i].push ((self.[](i,j))? \
self.[](i,j) : 0.0)
end
end
return Matrix.rows tab
end
end

mat3 = mat1.secu_sparse
puts "Unsparsed matrix = "
mat3.print

0 commentaires: