File: matrix.rb

package info (click to toggle)
ruby-graphviz 1.0.8-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,124 kB
  • ctags: 695
  • sloc: ruby: 7,656; xml: 26; makefile: 17
file content (221 lines) | stat: -rw-r--r-- 5,878 bytes parent folder | download | duplicates (5)
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