1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
class GraphViz
class Math
def self.Matrix( line, column = 0, val = 0 )
GraphViz::Math::Matrix.new(line, column, val)
end
class CoordinateError < RuntimeError
end
class ValueError < RuntimeError
end
class Matrix
def initialize( line_or_array, column = 0, val = 0 )
if line_or_array.kind_of?(Array)
line = line_or_array.size
column = nil
line_or_array.size.times do |l|
unless line_or_array[l].kind_of?(Array)
raise ArgumentError, "Wrong matrix definition"
end
column = line_or_array[l].size if column.nil?
unless line_or_array[l].size == column
raise ArgumentError, "Wrong matrix definition"
end
line_or_array[l].size.times do |c|
unless line_or_array[l][c].kind_of?(Numeric)
raise ValueError, "Element at [#{l+1}, #{c+1}] is not a number"
end
end
end
@matrix = line_or_array
@line = line
@column = column
elsif line_or_array.kind_of?(Integer) and column > 0
@matrix = Array.new(line_or_array)
@matrix.size.times do |l|
@matrix[l] = Array.new(column)
@matrix[l].size.times do |c|
@matrix[l][c] = val
end
end
@line = line_or_array
@column = column
else
raise ArgumentError, "Wrong matrix definition"
end
end
def [](line, column)
unless (0...@line).to_a.include?(line-1)
raise CoordinateError, "Line out of range (#{line} for 1..#{@line})!"
end
unless (0...@column).to_a.include?(column-1)
raise CoordinateError, "Column out of range (#{column} for 1..#{@column})!"
end
@matrix[line-1][column-1]
end
def []=( line, column, val )
unless (0...@line).to_a.include?(line-1)
raise CoordinateError, "Line out of range (#{line} for 1..#{@line})!"
end
unless (0...@column).to_a.include?(column-1)
raise CoordinateError, "Column out of range (#{column} for 1..#{@column})!"
end
@matrix[line-1][column-1] = val
end
def matrix
@matrix
end
alias :to_a :matrix
def columns
@column
end
def lines
@line
end
def to_s
size = bigger
out = ""
@line.times do |line|
out << "["
@column.times do |column|
out << sprintf(" %1$*2$s", @matrix[line][column].to_s, size)
end
out << "]\n"
end
return out
end
def -(m)
matrix = GraphViz::Math::Matrix.new( @line, @column )
@line.times do |line|
@column.times do |column|
matrix[line+1, column+1] = self[line+1, column+1] - m[line+1, column+1]
end
end
return matrix
end
def *(m)
matrix = GraphViz::Math::Matrix.new( @line, @line )
@line.times do |line|
@line.times do |column|
l = self.line(line+1)
c = m.column(column+1)
v = 0
l.size.times do |i|
v += l[i]*c[i]
end
matrix[line+1,column+1] = v
end
end
return matrix
end
def line( line )
unless (0...@line).to_a.include?(line-1)
raise CoordinateError, "Line out of range (#{line} for 1..#{@line})!"
end
@matrix[line-1]
end
def column( column )
col = []
unless (0...@column).to_a.include?(column-1)
raise CoordinateError, "Column out of range (#{column} for 1..#{@column})!"
end
@line.times do |line|
col << self[line+1, column]
end
return col
end
def transpose
matrix = GraphViz::Math::Matrix.new( @column, @line )
@line.times do |line|
@column.times do |column|
matrix[column+1, line+1] = self[line+1, column+1]
end
end
return matrix
end
def ==(m)
equal = true
@line.times do |line|
@column.times do |column|
equal &&= (m[line+1, column+1] == self[line+1, column+1])
end
end
return equal
end
def remove_line(n)
unless (0...@line).to_a.include?(n-1)
raise CoordinateError, "Line out of range (#{n} for 1..#{@line})!"
end
matrix = GraphViz::Math::Matrix.new( @line - 1, @column )
nline = 0
@line.times do |line|
next if line == n - 1
@column.times do |column|
matrix[nline+1, column+1] = self[line+1, column+1]
end
nline += 1
end
return matrix
end
def remove_column(n)
unless (0...@column).to_a.include?(n-1)
raise CoordinateError, "Column out of range (#{n} for 1..#{@column})!"
end
matrix = GraphViz::Math::Matrix.new( @line, @column - 1 )
@line.times do |line|
ncolumn = 0
@column.times do |column|
next if column == n - 1
matrix[line+1, ncolumn+1] = self[line+1, column+1]
ncolumn += 1
end
end
return matrix
end
def sum_of_column(n)
column(n).inject(0){|sum,item| sum + item}
end
def sum_of_line(n)
line(n).inject(0){|sum,item| sum + item}
end
def set_matrix(m) #:nodoc:
@matrix = m
end
private
def bigger
b = 0
@matrix.each do |line|
line.each do |column|
b = column.to_s.size if column.to_s.size > b
end
end
return b
end
end
end
end
|