math_expansion 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 02ca15e77c69bf92a0c178965cda06d7c3882d07
4
+ data.tar.gz: 65b6b03f99356b64cea1e9f442b49d7a778efe8b
5
+ SHA512:
6
+ metadata.gz: 53f7eed81c242e10dd77602a6128e3a42ae6c815325d568f6419e8583cb0376782ab63ef67ddfad47ecc696101871ce1a3589a183969af3b86aa1f2db1e10fa8
7
+ data.tar.gz: 5ab60e8a0fb97c1210fa33a23364d1845e057d4757072bd8daee0e903a4d25f7f4382429f57c7e1c88a03151ab31b90368be6c661b35e67fce24959ecde08ede
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *~
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-18mode # JRuby in 1.8 mode
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+ - rbx-18mode
7
+ - rbx-19mode
8
+ - 1.8.7
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in math_expansion.gemspec
4
+ gemspec
5
+ gem 'guard'
6
+ gem 'guard-rspec'
7
+ gem 'guard-bundler'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Eliasib Garcia, Daniel Herzog
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,26 @@
1
+ # MathExpansion
2
+
3
+ Útil gema de Ruby para representar matrices densas y dispersas.
4
+
5
+ ## Instalación
6
+
7
+ Añada esta línea al fichero Gemfile de su aplicación:
8
+
9
+ gem 'math_expansion'
10
+
11
+ Y a continuación ejecute:
12
+
13
+ $ bundle
14
+
15
+ O instale manualmente:
16
+
17
+ $ gem install math_expansion
18
+
19
+ ## Planteamiento
20
+
21
+ La clase Matriz contendrá el número de filas, número de columnas y un vector de contenido.
22
+
23
+ La matriz densa se representará como en la práctica anterior.
24
+ La matriz dispersa se representará como un Array que contendrá un Hash por cada fila. Cada par clave-valor del hash representará la fila de un elemento no nulo y el valor de ese elemento, respectivamente.
25
+
26
+ Las operaciones entre matrices se hará de manera natural, operando con las matrices dadas independientemente de que sean densas o dispersas. Dado que en cualquier operación puede cambiar el número de valores nulos de manera impredecible, será en la matriz resultado (en principio densa) donde se hará una comprobación de los valores nulos de la misma, y si éste es superior al 60%, la matriz resultado se convertirá a dispersa; en caso contrario, la matriz resultado seguirá siendo densa.
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ $:.unshift File.dirname(__FILE__) + 'lib'
2
+ $:.unshift './lib', './spec'
3
+
4
+ require "bundler/gem_tasks"
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default => :spec
10
+
11
+ desc "Espectativas de la clase Matriz"
12
+ task :test do
13
+ sh "rspec -I. spec/matriz_spec.rb --format documentation"
14
+ end
15
+
16
+ desc "Espectativas de la clase Matriz, con documentacion HTML"
17
+ task :thtml do
18
+ sh "rspec -I. spec/matriz_spec.rb --format html"
19
+ end
20
+
21
+ desc "Pruebas unitarias de las clases Matriz_Densa y Matriz_Dispersa"
22
+ task :tc do
23
+ sh "ruby -I. test/tc_mathexpansion.rb"
24
+ end
@@ -0,0 +1,12 @@
1
+ require "./lib/math_expansion/version"
2
+ require "./lib/math_expansion/matriz.rb"
3
+ require "./lib/math_expansion/matriz_densa.rb"
4
+ require "./lib/math_expansion/matriz_dispersa.rb"
5
+
6
+ require "./lib/math_expansion/racional.rb"
7
+ require "./lib/math_expansion/gcd.rb"
8
+
9
+ # Vacío
10
+ module MathExpansion
11
+
12
+ end
@@ -0,0 +1,9 @@
1
+ module MathExpansion
2
+ def self.gcd(a, b)
3
+ a, b = a.abs, b.abs
4
+ while b != 0
5
+ a, b = b, a % b
6
+ end
7
+ a
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ require './lib/math_expansion/racional.rb'
2
+
3
+ module MathExpansion
4
+ class Matriz
5
+ attr_reader :N, :M
6
+ attr_accessor :contenido
7
+
8
+ def initialize(n, m)
9
+ raise ArgumentError, 'Indice no valido' unless n.is_a? Fixnum and n > 0 and m.is_a? Fixnum and m > 0
10
+
11
+ @N, @M = n, m
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,191 @@
1
+ require "./lib/math_expansion/matriz.rb"
2
+
3
+ module MathExpansion
4
+ class Matriz_Densa < Matriz
5
+ def initialize(n, m)
6
+ super
7
+
8
+ @contenido = Array.new(@N,0)
9
+ i = 0
10
+ while i < @N
11
+ @contenido[i] = Array.new(@M,0)
12
+ i += 1
13
+ end
14
+ end
15
+
16
+ def get(i, j)
17
+ if( i < 0 or i >=@N or j < 0 or j >= @M)
18
+ return nil
19
+ end
20
+
21
+ @contenido[i][j]
22
+ end
23
+
24
+ def null_percent
25
+ total = @N*@M
26
+ no_nulos = 0
27
+
28
+ i = 0
29
+ while(i < @N)
30
+ j = 0
31
+ while(j < @M)
32
+ if(@contenido[i][j] != @contenido[i][j].class.null)
33
+ no_nulos += 1
34
+ end
35
+ j += 1
36
+ end
37
+ i += 1
38
+ end
39
+
40
+ nulos = total - no_nulos
41
+ nulos.to_f/total.to_f
42
+ end #endmethod null_percent
43
+
44
+ def set(i, j, value)
45
+ if( i < 0 or i >=@N or j < 0 or j >= @M)
46
+ return nil
47
+ end
48
+
49
+ if(!(value.class.respond_to? :null))
50
+ puts "Se debe definir el metodo \"null\" que devuelva un elemento nulo para la clase #{value.class}"
51
+ return nil
52
+ end
53
+
54
+ # Contar elementos nulos y comprobar si se hace una matriz dispersa
55
+ # De momento, no dejamos añadir elementos nulos
56
+ # ¿o si?
57
+ #if(value != nil and value != value.class.null) # Y se puede comprobar para todos los tipos si es necesario. (con un método zero, por ejemplo)
58
+ @contenido[i][j] = value
59
+ #end
60
+ end
61
+
62
+ def to_s
63
+ s = ""
64
+ i = 0
65
+ while(i < @N)
66
+ j = 0
67
+ while(j < @M)
68
+ s += "#{@contenido[i][j].to_s}\t"
69
+ j += 1
70
+ end
71
+ s += "\n"
72
+ i += 1
73
+ end
74
+ s
75
+ end
76
+
77
+ def +(other)
78
+ raise ArgumentError , 'Tipo invalido' unless other.is_a? Matriz
79
+ raise ArgumentError , 'Matriz no compatible' unless @N == other.N and @M == other.M
80
+
81
+ c = Matriz_Densa.new(@N, @M)
82
+ i = 0
83
+ while(i < @N)
84
+ j = 0
85
+ while(j < @M)
86
+ c.set(i, j, get(i,j) + other.get(i,j))
87
+ j += 1
88
+ end
89
+ i += 1
90
+ end
91
+ if (c.null_percent > 0.6)
92
+ c = MathExpansion::Matriz_Dispersa.copy(c)
93
+ end
94
+ c
95
+ end
96
+
97
+ def -(other)
98
+ raise ArgumentError , 'Tipo invalido' unless other.is_a? Matriz
99
+ raise ArgumentError , 'Matriz no compatible' unless @N == other.N and @M == other.M
100
+
101
+ c = Matriz_Densa.new(@N, @M)
102
+ i = 0
103
+ while(i < @N)
104
+ j = 0
105
+ while(j < @M)
106
+ c.set(i, j, get(i,j) - other.get(i,j))
107
+ j += 1
108
+ end
109
+ i += 1
110
+ end
111
+ if (c.null_percent > 0.6)
112
+ c = MathExpansion::Matriz_Dispersa.copy(c)
113
+ end
114
+ c
115
+ end
116
+
117
+ def *(other)
118
+ raise ArgumentError , 'Parametro invalido' unless other.is_a? Numeric or other.is_a? Matriz
119
+
120
+ if(other.is_a? Numeric) # Matriz * numero
121
+ c = Matriz_Densa.new(@N, @M)
122
+ i = 0
123
+ while(i < @N)
124
+ j = 0
125
+ while(j < @M)
126
+ c.set(i, j, get(i,j)*other)
127
+ j += 1
128
+ end # while j
129
+ i += 1
130
+ end # while i
131
+ else # Matriz * Matriz
132
+ raise ArgumentError , 'Matriz no compatible (A.N == B.M)' unless @M == other.N
133
+ c = Matriz_Densa.new(@N, other.M)
134
+ i = 0
135
+ while(i < @N)
136
+ j = 0
137
+ while(j < other.M)
138
+ k = 0
139
+ #if (get(i,j).is_a? Fraccion)
140
+ # c.set(i, j, Fraccion.null
141
+ #else
142
+ # c.set(i, j, 0)
143
+ #end
144
+ while(k < @M)
145
+ c.set(i, j, get(i, k) * other.get(k,j) + c.get(i,j))
146
+ k += 1
147
+ end # while k
148
+ j += 1
149
+ end # while j
150
+ i += 1
151
+ end # while i
152
+ end # while else
153
+ if (c.null_percent > 0.6)
154
+ c = MathExpansion::Matriz_Dispersa.copy(c)
155
+ end
156
+ c
157
+ end # *(other)
158
+
159
+ def max
160
+ m = get(0,0)
161
+ i = 0
162
+ while(i < @N)
163
+ j = 0
164
+ while(j < @M)
165
+ if (get(i,j) > m)
166
+ m = get(i,j)
167
+ end
168
+ j += 1
169
+ end
170
+ i += 1
171
+ end
172
+ m
173
+ end
174
+
175
+ def min
176
+ m = get(0,0)
177
+ i = 0
178
+ while(i < @N)
179
+ j = 0
180
+ while(j < @M)
181
+ if (get(i,j) < m)
182
+ m = get(i,j)
183
+ end
184
+ j += 1
185
+ end
186
+ i += 1
187
+ end
188
+ m
189
+ end # Method min
190
+ end # Class
191
+ end # Module
@@ -0,0 +1,250 @@
1
+ require "./lib/math_expansion/matriz.rb"
2
+ require "./lib/math_expansion/matriz_densa.rb"
3
+
4
+ module MathExpansion
5
+ class Matriz_Dispersa < Matriz
6
+ def reset
7
+ @contenido = Array.new(@N) # Array con @N filas y ninguna columna (vacio)
8
+ i = 0
9
+ while(i < @N)
10
+ @contenido[i] = {}
11
+ i += 1
12
+ end
13
+ end
14
+
15
+ def initialize(n, m)
16
+ super
17
+ reset
18
+ end
19
+
20
+ # Metodo factoria
21
+ def self.copy(matriz)
22
+ raise ArgumentError, 'Tipo invalido' unless matriz.is_a? MathExpansion::Matriz_Densa
23
+ obj = new(matriz.N, matriz.M)
24
+
25
+ i = 0
26
+ while(i < matriz.N)
27
+ j = 0
28
+ while(j < matriz.M)
29
+ value = matriz.get(i,j)
30
+ raise RuntimeError , "No se ha definido \"null\" para la clase #{value.class}" unless value.class.respond_to? :null
31
+
32
+ if( value != value.class.null)
33
+ obj.contenido[i][j] = value
34
+ end #endif
35
+ j += 1
36
+ end #endwhile j
37
+ i += 1
38
+ end #endwhile i
39
+ obj
40
+ end #endmethod copy
41
+
42
+ def null_percent
43
+ total = @N*@M
44
+ no_nulos = 0
45
+
46
+ i = 0
47
+ while(i < @N)
48
+ no_nulos += @contenido[i].size # Nunca habra elementos nulos en alguna fila
49
+ i += 1
50
+ end
51
+
52
+ nulos = total - no_nulos
53
+ nulos.to_f/total.to_f
54
+ end #endmethod null_percent
55
+
56
+ def get(i, j)
57
+ if( !(i.is_a? Fixnum) or i < 0 or i >=@N or !(j.is_a? Fixnum) or j < 0 or j >= @M)
58
+ return nil
59
+ end
60
+
61
+ if(@contenido[i][j] != nil) # Elemento no nulo (esta en el hash)
62
+ return @contenido[i][j]
63
+ else # Elemento nulo (no esta en el Hash)
64
+ return 0
65
+ end
66
+ end #endmethod get
67
+
68
+ def set(i, j, value)
69
+ if(!(value.class.respond_to? :null))
70
+ puts "Se debe definir el metodo \"null\" que devuelva un elemento nulo para la clase #{value.class}"
71
+ return nil
72
+ end
73
+
74
+ if( !(i.is_a? Fixnum) or i < 0 or i >=@N or !(j.is_a? Fixnum) or j < 0 or j >= @M)
75
+ return nil
76
+ end
77
+
78
+ if(value == nil or value == value.class.null)
79
+ @contenido[i].delete(j) # Borrar elemento (valor nulo)
80
+ else
81
+ @contenido[i][j] = value
82
+ end
83
+
84
+ if(null_percent < 0.6) # Si se ha sobrepasado el número de elementos nulos, borramos el último elemento modificado
85
+ @contenido[i].delete(j)
86
+ puts "Borrado el elemento #{i},#{j} por sobrepasar el numero de elementos no nulos (Porcentaje actual: #{null_percent}"
87
+ end
88
+
89
+ end #endmethod set
90
+
91
+ def to_s
92
+ # Ejemplo: "Fila 0: \nFila 1: 0=>1 1=>3 \nFila 2: \n"
93
+ # 0 0
94
+ # 1 3
95
+ # 0 0
96
+ i = 0
97
+ output = ""
98
+ while(i < @N)
99
+ output += "Fila #{i}: "
100
+ @contenido[i].sort.each{|k, v| output += "#{k.to_s}=>#{v.to_s} "}
101
+ output += "\n"
102
+ i += 1
103
+ end
104
+ output
105
+ end
106
+
107
+ def +(other)
108
+ raise ArgumentError , 'Tipo invalido' unless other.is_a? Matriz
109
+ raise ArgumentError , 'Matriz no compatible' unless @N == other.N and @M == other.M
110
+
111
+ c = Matriz_Densa.new(@N, @M)
112
+ i = 0
113
+ while(i < @N)
114
+ j = 0
115
+ while(j < @M)
116
+ c.set(i, j, get(i,j) + other.get(i,j))
117
+ j += 1
118
+ end
119
+ i += 1
120
+ end
121
+ if(c.null_percent > 0.6)
122
+ c = Matriz_Dispersa.copy(c)
123
+ end
124
+ c
125
+ end
126
+
127
+ def -(other)
128
+ raise ArgumentError , 'Tipo invalido' unless other.is_a? Matriz
129
+ raise ArgumentError , 'Matriz no compatible' unless @N == other.N and @M == other.M
130
+
131
+ c = Matriz_Densa.new(@N, @M)
132
+ i = 0
133
+ while(i < @N)
134
+ j = 0
135
+ while(j < @M)
136
+ c.set(i, j, get(i,j) - other.get(i,j))
137
+ j += 1
138
+ end
139
+ i += 1
140
+ end
141
+ if(c.null_percent > 0.6)
142
+ c = Matriz_Dispersa.copy(c)
143
+ end
144
+ c
145
+ end
146
+
147
+ def *(other)
148
+ raise ArgumentError , 'Parametro invalido' unless other.is_a? Numeric or other.is_a? Matriz
149
+
150
+ if(other.is_a? Numeric) # Matriz * numero
151
+ c = Matriz_Densa.new(@N, @M)
152
+ i = 0
153
+ while(i < @N)
154
+ j = 0
155
+ while(j < @M)
156
+ c.set(i, j, get(i,j)*other)
157
+ j += 1
158
+ end # while j
159
+ i += 1
160
+ end # while i
161
+ else # Matriz * Matriz
162
+ raise ArgumentError , 'Matriz no compatible (A.N == B.M)' unless @M == other.N
163
+ c = Matriz_Densa.new(@N, other.M)
164
+ i = 0
165
+ while(i < @N)
166
+ j = 0
167
+ while(j < other.M)
168
+ k = 0
169
+ #if (get(i,j).is_a? Fraccion)
170
+ # c.set(i, j, Fraccion.null
171
+ #else
172
+ # c.set(i, j, 0)
173
+ #end
174
+ while(k < @M)
175
+ c.set(i, j, get(i, k) * other.get(k,j) + c.get(i,j))
176
+ k += 1
177
+ end # while k
178
+ j += 1
179
+ end # while j
180
+ i += 1
181
+ end # while i
182
+ end # while else
183
+ if(c.null_percent > 0.6)
184
+ c = Matriz_Dispersa.copy(c)
185
+ end
186
+ c
187
+ end # *(other)
188
+
189
+ def max
190
+ if(null_percent == 1.0)
191
+ return nil # o return 0
192
+ end
193
+
194
+ # Valor máximo: si todos los elementos son menores que el elemento nulo
195
+ # Se devolverá el mayor elemento no nulo.
196
+ max = nil
197
+
198
+ # Asignar al primer valor no-nulo de la matriz
199
+ i = 0
200
+ while(max == nil)
201
+ if(@contenido[i].size != 0)
202
+ max = @contenido[i].values[0]
203
+ end
204
+ i += 1
205
+ end
206
+
207
+ # Iterar por todos los elementos no nulos para encontrar el maximo
208
+ i = 0
209
+ while(i < @contenido.size)
210
+ if(@contenido[i].values.max != nil and @contenido[i].values.max > max)
211
+ max = @contenido[i].values.max
212
+ end
213
+ i += 1
214
+ end
215
+
216
+ max
217
+ end
218
+
219
+ def min
220
+ if(null_percent == 1.0)
221
+ return nil # o return 0
222
+ end
223
+
224
+ # Valor máximo: si todos los elementos son menores que el elemento nulo
225
+ # Se devolverá el mayor elemento no nulo.
226
+ min = nil
227
+
228
+ # Asignar al primer valor no-nulo de la matriz
229
+ i = 0
230
+ while(min == nil)
231
+ if(@contenido[i].size != 0)
232
+ min = @contenido[i].values[0]
233
+ end
234
+ i += 1
235
+ end
236
+
237
+ # Iterar por todos los elementos no nulos para encontrar el maximo
238
+ i = 0
239
+ while(i < @contenido.size)
240
+ if(@contenido[i].values.min != nil and @contenido[i].values.min < min)
241
+ min = @contenido[i].values.min
242
+ end
243
+ i += 1
244
+ end
245
+
246
+ min
247
+ end
248
+
249
+ end #endclass
250
+ end #end module