algebra 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +53 -0
  3. data/.travis.yml +7 -0
  4. data/CODE_OF_CONDUCT.md +49 -0
  5. data/Gemfile +7 -0
  6. data/Gemfile.lock +28 -0
  7. data/LICENSE.txt +21 -0
  8. data/README-ja.txt +60 -0
  9. data/README.md +61 -0
  10. data/Rakefile +43 -0
  11. data/algebra.gemspec +33 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/doc-ja/README-ja.html +69 -0
  15. data/doc-ja/README-ja.rd +60 -0
  16. data/doc-ja/README.html +0 -0
  17. data/doc-ja/README.rd +0 -0
  18. data/doc-ja/algebra-ja.html +66 -0
  19. data/doc-ja/algebra-ja.rd +60 -0
  20. data/doc-ja/algebraic-equation-ja.html +36 -0
  21. data/doc-ja/algebraic-equation-ja.rd +26 -0
  22. data/doc-ja/algebraic-extension-field-ja.html +122 -0
  23. data/doc-ja/algebraic-extension-field-ja.rd +118 -0
  24. data/doc-ja/algebraic-parser-ja.html +87 -0
  25. data/doc-ja/algebraic-parser-ja.rd +95 -0
  26. data/doc-ja/changes.html +161 -0
  27. data/doc-ja/changes.rd +119 -0
  28. data/doc-ja/elementary-divisor-ja.html +56 -0
  29. data/doc-ja/elementary-divisor-ja.rd +45 -0
  30. data/doc-ja/euclidian-ring-ja.html +78 -0
  31. data/doc-ja/euclidian-ring-ja.rd +69 -0
  32. data/doc-ja/finite-group-ja.html +285 -0
  33. data/doc-ja/finite-group-ja.rd +276 -0
  34. data/doc-ja/finite-map-ja.html +224 -0
  35. data/doc-ja/finite-map-ja.rd +227 -0
  36. data/doc-ja/finite-set-ja.html +393 -0
  37. data/doc-ja/finite-set-ja.rd +408 -0
  38. data/doc-ja/index-ja.html +113 -0
  39. data/doc-ja/index-ja.rd +112 -0
  40. data/doc-ja/jordan-form-ja.html +106 -0
  41. data/doc-ja/jordan-form-ja.rd +99 -0
  42. data/doc-ja/localized-ring-ja.html +121 -0
  43. data/doc-ja/localized-ring-ja.rd +131 -0
  44. data/doc-ja/m-polynomial-ja.html +542 -0
  45. data/doc-ja/m-polynomial-ja.rd +596 -0
  46. data/doc-ja/matrix-algebra-ja.html +686 -0
  47. data/doc-ja/matrix-algebra-ja.rd +727 -0
  48. data/doc-ja/matrix-algebra-triplet-ja.html +124 -0
  49. data/doc-ja/matrix-algebra-triplet-ja.rd +129 -0
  50. data/doc-ja/permutation-group-ja.html +159 -0
  51. data/doc-ja/permutation-group-ja.rd +151 -0
  52. data/doc-ja/polynomial-converter-ja.html +64 -0
  53. data/doc-ja/polynomial-converter-ja.rd +54 -0
  54. data/doc-ja/polynomial-ja.html +446 -0
  55. data/doc-ja/polynomial-ja.rd +473 -0
  56. data/doc-ja/residue-class-ring-ja.html +112 -0
  57. data/doc-ja/residue-class-ring-ja.rd +113 -0
  58. data/doc-ja/sample-algebraic-equation01.rb.v.rd +11 -0
  59. data/doc-ja/sample-algebraic-equation02.rb.v.rd +11 -0
  60. data/doc-ja/sample-algebraic-root01.rb.v.rd +20 -0
  61. data/doc-ja/sample-algebraicfield01.rb.v.rd +26 -0
  62. data/doc-ja/sample-algebraicfield02.rb.v.rd +15 -0
  63. data/doc-ja/sample-cayleyhamilton01.rb.v.rd +14 -0
  64. data/doc-ja/sample-diagonalization01.rb.v.rd +48 -0
  65. data/doc-ja/sample-divmod01.rb.v.rd +17 -0
  66. data/doc-ja/sample-elementary-divisor01.rb.v.rd +48 -0
  67. data/doc-ja/sample-factorize01.rb.v.rd +11 -0
  68. data/doc-ja/sample-factorize02.rb.v.rd +13 -0
  69. data/doc-ja/sample-factorize03.rb.v.rd +14 -0
  70. data/doc-ja/sample-factorize04.rb.v.rd +14 -0
  71. data/doc-ja/sample-factorize05.rb.v.rd +53 -0
  72. data/doc-ja/sample-galois-group01.rb.v.rd +27 -0
  73. data/doc-ja/sample-gaussian-elimination01.rb.v.rd +19 -0
  74. data/doc-ja/sample-geometry01.rb.v.rd +33 -0
  75. data/doc-ja/sample-geometry02.rb.v.rd +34 -0
  76. data/doc-ja/sample-geometry03.rb.v.rd +45 -0
  77. data/doc-ja/sample-geometry04.rb.v.rd +33 -0
  78. data/doc-ja/sample-geometry07.rb.v.rd +62 -0
  79. data/doc-ja/sample-groebner01.rb.v.rd +13 -0
  80. data/doc-ja/sample-groebner02.rb.v.rd +18 -0
  81. data/doc-ja/sample-groebner03.rb.v.rd +19 -0
  82. data/doc-ja/sample-group01.rb.v.rd +21 -0
  83. data/doc-ja/sample-jordan-form01.rb.v.rd +56 -0
  84. data/doc-ja/sample-jordanform01.rb.v.rd +55 -0
  85. data/doc-ja/sample-lagrange-multiplier01.rb.v.rd +35 -0
  86. data/doc-ja/sample-m-factorize01.rb.v.rd +15 -0
  87. data/doc-ja/sample-m-factorize02.rb.v.rd +12 -0
  88. data/doc-ja/sample-m-polynomial01.rb.v.rd +10 -0
  89. data/doc-ja/sample-map01.rb.v.rd +9 -0
  90. data/doc-ja/sample-polynomial01.rb.v.rd +9 -0
  91. data/doc-ja/sample-polynomial02.rb.v.rd +11 -0
  92. data/doc-ja/sample-primefield01.rb.v.rd +13 -0
  93. data/doc-ja/sample-quotientfield01.rb.v.rd +11 -0
  94. data/doc-ja/sample-quotientfield02.rb.v.rd +18 -0
  95. data/doc-ja/sample-quotientfield03.rb.v.rd +16 -0
  96. data/doc-ja/sample-quotientfield04.rb.v.rd +16 -0
  97. data/doc-ja/sample-set01.rb.v.rd +18 -0
  98. data/doc-ja/sample-splitting-field01.rb.v.rd +19 -0
  99. data/doc-ja/samples-ja.html +885 -0
  100. data/doc-ja/samples-ja.rd +221 -0
  101. data/doc-ja/style.css +85 -0
  102. data/doc-ja/todo.html +20 -0
  103. data/doc-ja/todo.rd +9 -0
  104. data/lib/algebra.rb +36 -0
  105. data/lib/algebra/algebraic-equation.rb +56 -0
  106. data/lib/algebra/algebraic-extension-field.rb +135 -0
  107. data/lib/algebra/algebraic-parser.rb +160 -0
  108. data/lib/algebra/algebraic-system.rb +224 -0
  109. data/lib/algebra/annihilate.rb +52 -0
  110. data/lib/algebra/array-supplement.rb +53 -0
  111. data/lib/algebra/auto-require.rb +84 -0
  112. data/lib/algebra/chinese-rem-th.rb +135 -0
  113. data/lib/algebra/combinatorial.rb +145 -0
  114. data/lib/algebra/elementary-divisor.rb +193 -0
  115. data/lib/algebra/euclidian-ring.rb +161 -0
  116. data/lib/algebra/factors.rb +305 -0
  117. data/lib/algebra/finite-group.rb +374 -0
  118. data/lib/algebra/finite-map.rb +201 -0
  119. data/lib/algebra/finite-set.rb +456 -0
  120. data/lib/algebra/galois-group.rb +129 -0
  121. data/lib/algebra/gaussian-elimination.rb +385 -0
  122. data/lib/algebra/groebner-basis-coeff.rb +228 -0
  123. data/lib/algebra/groebner-basis.rb +197 -0
  124. data/lib/algebra/import-module-single-thread.rb +86 -0
  125. data/lib/algebra/import-module.rb +491 -0
  126. data/lib/algebra/jordan-form.rb +114 -0
  127. data/lib/algebra/linear-algebra.rb +143 -0
  128. data/lib/algebra/localized-ring.rb +294 -0
  129. data/lib/algebra/m-index.rb +282 -0
  130. data/lib/algebra/m-polynomial-factor-int.rb +186 -0
  131. data/lib/algebra/m-polynomial-factor-zp.rb +114 -0
  132. data/lib/algebra/m-polynomial-factor.rb +315 -0
  133. data/lib/algebra/m-polynomial-gcd.rb +40 -0
  134. data/lib/algebra/m-polynomial.rb +875 -0
  135. data/lib/algebra/matrix-algebra-triplet.rb +292 -0
  136. data/lib/algebra/matrix-algebra.rb +929 -0
  137. data/lib/algebra/numeric-supplement.rb +123 -0
  138. data/lib/algebra/permutation-group.rb +257 -0
  139. data/lib/algebra/polynomial-converter.rb +193 -0
  140. data/lib/algebra/polynomial-factor-alg.rb +148 -0
  141. data/lib/algebra/polynomial-factor-int.rb +252 -0
  142. data/lib/algebra/polynomial-factor-zp.rb +165 -0
  143. data/lib/algebra/polynomial-factor.rb +140 -0
  144. data/lib/algebra/polynomial.rb +592 -0
  145. data/lib/algebra/powers.rb +31 -0
  146. data/lib/algebra/prime-gen.rb +32 -0
  147. data/lib/algebra/rational.rb +81 -0
  148. data/lib/algebra/residue-class-ring.rb +219 -0
  149. data/lib/algebra/sets-system.rb +43 -0
  150. data/lib/algebra/splitting-field.rb +103 -0
  151. data/lib/algebra/version.rb +3 -0
  152. data/sample/Makefile +10 -0
  153. data/sample/do-testscripts.rb +100 -0
  154. data/sample/sample-algebraic-equation01.rb +6 -0
  155. data/sample/sample-algebraic-equation02.rb +6 -0
  156. data/sample/sample-algebraic-root01.rb +15 -0
  157. data/sample/sample-algebraicfield01.rb +21 -0
  158. data/sample/sample-algebraicfield02.rb +10 -0
  159. data/sample/sample-cayleyhamilton01.rb +9 -0
  160. data/sample/sample-diagonalization01.rb +43 -0
  161. data/sample/sample-divmod01.rb +12 -0
  162. data/sample/sample-elementary-divisor01.rb +43 -0
  163. data/sample/sample-factorize01.rb +6 -0
  164. data/sample/sample-factorize02.rb +8 -0
  165. data/sample/sample-factorize03.rb +9 -0
  166. data/sample/sample-factorize04.rb +9 -0
  167. data/sample/sample-factorize05.rb +48 -0
  168. data/sample/sample-galois-group01.rb +22 -0
  169. data/sample/sample-gaussian-elimination01.rb +14 -0
  170. data/sample/sample-geometry01.rb +28 -0
  171. data/sample/sample-geometry02.rb +29 -0
  172. data/sample/sample-geometry03.rb +40 -0
  173. data/sample/sample-geometry04.rb +28 -0
  174. data/sample/sample-geometry07.rb +58 -0
  175. data/sample/sample-groebner01.rb +8 -0
  176. data/sample/sample-groebner02.rb +13 -0
  177. data/sample/sample-groebner03.rb +14 -0
  178. data/sample/sample-group01.rb +16 -0
  179. data/sample/sample-jordan-form01.rb +51 -0
  180. data/sample/sample-lagrange-multiplier01.rb +30 -0
  181. data/sample/sample-m-factorize01.rb +10 -0
  182. data/sample/sample-m-factorize02.rb +7 -0
  183. data/sample/sample-m-polynomial01.rb +5 -0
  184. data/sample/sample-map01.rb +4 -0
  185. data/sample/sample-polynomial01.rb +4 -0
  186. data/sample/sample-polynomial02.rb +6 -0
  187. data/sample/sample-primefield01.rb +8 -0
  188. data/sample/sample-quotientfield01.rb +6 -0
  189. data/sample/sample-quotientfield02.rb +13 -0
  190. data/sample/sample-quotientfield03.rb +11 -0
  191. data/sample/sample-quotientfield04.rb +11 -0
  192. data/sample/sample-set01.rb +13 -0
  193. data/sample/sample-splitting-field01.rb +14 -0
  194. data/sample/test-00-cayley-hamilton.rb +76 -0
  195. data/sample/test-00-groebner-basis.rb +274 -0
  196. data/sample/test-00-polynomial-factor-alg.rb +89 -0
  197. data/sample/test-00.list +4 -0
  198. data/sample/time-trial.rb +65 -0
  199. metadata +373 -0
@@ -0,0 +1,875 @@
1
+ # Multivariate polynomial ring class over arbitary ring
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.6 (2002.02.05)
6
+
7
+ require "algebra/import-module-single-thread"
8
+ require "algebra/m-index"
9
+ require "algebra/algebraic-system"
10
+ module Algebra
11
+ autoload :Groebner, "algebra/groebner-basis"
12
+ def MPolynomial(ground, *vars)
13
+ Algebra::MPolynomial.create(ground, *vars)
14
+ end
15
+ module_function :MPolynomial
16
+
17
+ class MPolynomial
18
+ auto_req_init
19
+ auto_req(:value_on, "algebra/polynomial-converter"){
20
+ include MPolynomialConverter
21
+ }
22
+ auto_req_s_init
23
+ auto_req_s(:convert_to, "algebra/polynomial-converter"){
24
+ extend MPolynomialConvertTo
25
+ }
26
+
27
+ =begin
28
+ class MonomialOrder
29
+ def initialize(ord = :lex, t = nil)
30
+ # ord ||= :lex
31
+ case ord
32
+ when Symbol
33
+ @ord_str = ord.id2name
34
+ @ord_sym = ord
35
+ when String
36
+ @ord_sym = ord.intern
37
+ @ord_str = ord
38
+ else
39
+ raise "want Symbol or String"
40
+ end
41
+
42
+ if t
43
+ @t = t
44
+ instance_eval("alias cmp #{@ord_str}_t")
45
+ else
46
+ instance_eval("alias cmp #@ord_str")
47
+ end
48
+ end
49
+
50
+ def to_s; @ord_str; end
51
+ def to_sym; @ord_sym; end
52
+ def v_ord; @t; end
53
+
54
+ #standerd ordering
55
+ def lex(me, other)
56
+ me.to_a <=> other.to_a
57
+ end
58
+
59
+ def grlex(me, other)
60
+ s = (me.totdeg <=> other.totdeg)
61
+ return s unless s.zero?
62
+ lex(me, other)
63
+ end
64
+
65
+ def grevlex(me, other)
66
+ s = (me.totdeg <=> other.totdeg)
67
+ return s unless s.zero?
68
+ n = [me.size, other.size].max
69
+ (n-1).downto 0 do |i|
70
+ x = other[i] - me[i]
71
+ return x unless x.zero?
72
+ end
73
+ 0
74
+ end
75
+
76
+ #ordering by transition array
77
+ def lex_t(me, other)
78
+ n = [me.size, other.size].max
79
+ 0.upto (n-1) do |i|
80
+ x = me[@t[i]] - other[@t[i]]
81
+ return x unless x.zero?
82
+ end
83
+ 0
84
+ end
85
+
86
+ def grlex_t(me, other)
87
+ s = (me.totdeg <=> other.totdeg)
88
+ return s unless s.zero?
89
+ lex_t(me, other)
90
+ end
91
+
92
+ def grevlex_t(me, other)
93
+ s = (me.totdeg <=> other.totdeg)
94
+ return s unless s.zero?
95
+ n = [me.size, other.size].max
96
+ (n-1).downto 0 do |i|
97
+ x = other[@t[i]] - me[@t[i]]
98
+ return x unless x.zero?
99
+ end
100
+ 0
101
+ end
102
+ end
103
+ =end
104
+
105
+ include Enumerable
106
+ include Comparable
107
+ extend AlgebraCreator
108
+ include AlgebraBase
109
+ auto_req :factorize, "algebra/m-polynomial-factor"
110
+ auto_req :divmod_s, "algebra/groebner-basis"
111
+ auto_req :S_pair, "algebra/groebner-basis"
112
+ auto_req :S_pair_coeff, "algebra/groebner-basis"
113
+
114
+ def initialize(ha = {})
115
+ @bone = ha
116
+ method_cash_clear
117
+ end
118
+
119
+ def self.create(ground, *vars)
120
+ klass = super(ground)
121
+ klass.sysvar(:order, nil)
122
+ klass.sysvar(:v_order, nil)
123
+ klass.set_ord(:lex)
124
+ klass.sysvar(:variables, vars)
125
+ klass.sysvar(:display_type, :norm)
126
+ klass
127
+ end
128
+
129
+ def variables; self.class.variables; end
130
+ def vars; self.class.vars; end
131
+
132
+ def self.vars(*vs)
133
+ if vs.size > 0
134
+ vs = vs[0].scan(/[a-zA-Z]_?\d*/) if vs.size == 1 && vs[0].is_a?(String)
135
+ vs.collect{|var| indeterminate(var)}
136
+ else
137
+ variables.collect{|var| indeterminate(var) }
138
+ end
139
+ end
140
+
141
+ def self.to_ary
142
+ [self, *vars]
143
+ end
144
+
145
+ def self.indeterminate(obj)
146
+ ind = if i = variables.index(obj)
147
+ [0] * i + [1]
148
+ # Algebra::MIndex.monomial(i)
149
+ else
150
+ variables.push obj
151
+ # [0] * (variables.size-1) + [1]
152
+ Algebra::MIndex.monomial(variables.size-1)
153
+ end
154
+ monomial(ind)
155
+ end
156
+
157
+ def self.var(obj)
158
+ indeterminate(obj)
159
+ end
160
+
161
+ def self.mvar(*array)
162
+ if array.empty?
163
+ variables.collect{|var| indeterminate(var) }
164
+ else
165
+ array.collect{|var| indeterminate(var)}
166
+ end
167
+ end
168
+
169
+ def self.monomial(ind = [1], c = ground.unity)
170
+ new({Algebra::MIndex[*ind] => c})
171
+ end
172
+
173
+ def monomial(ind = [1], c = ground.unity)
174
+ self.class.monomial(ind, c)
175
+ end
176
+
177
+ def self.const(x)
178
+ new({Algebra::MIndex::Unity => x})
179
+ end
180
+
181
+ def self.regulate(x)
182
+ if x.is_a? self
183
+ x
184
+ elsif y = ground.regulate(x)
185
+ const(y)
186
+ else
187
+ nil
188
+ end
189
+ end
190
+
191
+ def self.[](*x)
192
+ new(Hash[*x])
193
+ end
194
+
195
+ def self.euclidian?
196
+ ground.euclidian? && variables.size <= 1
197
+ end
198
+
199
+ def self.ufd?
200
+ euclidian? || ground.field?
201
+ end
202
+
203
+ def each(&b); @bone.each(&b); end
204
+
205
+ def keys; @bone.keys; end
206
+
207
+ def values; @bone.values; end
208
+
209
+ def [](ind)
210
+ @bone[ind] || 0
211
+ end
212
+
213
+ def []=(ind, c)
214
+ @bone[ind] = c
215
+ end
216
+
217
+ def monomial?
218
+ flag = false
219
+ each do |m, c|
220
+ unless c.zero?
221
+ if flag
222
+ return false
223
+ else
224
+ flag = true
225
+ end
226
+ end
227
+ end
228
+ flag
229
+ end
230
+
231
+ def constant?
232
+ each do |m, c|
233
+ if m.totdeg > 0 && !c.zero?
234
+ return false
235
+ end
236
+ end
237
+ true
238
+ end
239
+
240
+ def unit?
241
+ constant? && lc.unit?
242
+ end
243
+
244
+ def constant_coeff
245
+ # we assume {[]=>2, [0]=>3} is not appeared.
246
+ # it must be reduced to {[]=>6}.
247
+ @bone[Algebra::MIndex::Unity]
248
+ # k = ground.unity
249
+ # @bone.each do |ind, c|
250
+ # unless c.zero?
251
+ # k *= c if ind.totdeg == 0
252
+ # end
253
+ # end
254
+ # k
255
+ end
256
+
257
+ def include?(k)
258
+ @bone.include?(k)
259
+ end
260
+
261
+ def self.zero; new; end
262
+
263
+ def self.unity; const(ground.unity); end
264
+
265
+ def zero?; !find{|m, c| !c.zero?}; end
266
+
267
+ def self.set_ord(ord = nil, v_ord = nil)
268
+ # @@order = MonomialOrder.new(ord, v_ord)
269
+ if ord.is_a? String
270
+ ord = ord.intern
271
+ elsif ord.is_a?(Symbol) || ord.nil?
272
+ else
273
+ raise "#{ord} must be String or Symbol"
274
+ end
275
+ if v_ord.is_a? String
276
+ v_ord = v_ord.intern
277
+ elsif v_ord.is_a?(Symbol) || v_ord.nil?
278
+ else
279
+ raise "#{v_ord} must be String or Symbol"
280
+ end
281
+
282
+ if ord.nil?
283
+ ord = get_ord
284
+ end
285
+ # self.order = MonomialOrder.new(ord, v_ord) #o
286
+ self.order = ord if ord #n
287
+ self.v_order = v_ord if v_ord #n
288
+
289
+ MIndex.set_ord(ord) if ord #n
290
+ MIndex.set_v_ord(v_ord) if v_ord #n
291
+ end
292
+
293
+ def self.ord=(ord)
294
+ self.set_ord(ord, nil)
295
+ end
296
+
297
+ def self.get_ord
298
+ order
299
+ end
300
+
301
+ def self.ord
302
+ get_ord
303
+ end
304
+
305
+ def self.get_v_ord
306
+ v_order
307
+ end
308
+
309
+ def self.with_ord_old(ord = nil, v_ord = nil, methods = [])
310
+ method_cash_clear(*methods)
311
+ o_ord, o_v_ord = get_ord, get_v_ord
312
+ result = nil
313
+ begin
314
+ set_ord(ord, v_ord)
315
+ result = yield
316
+ ensure
317
+ set_ord(o_ord, o_v_ord)
318
+ end
319
+ result
320
+ end
321
+
322
+ def self.with_ord(ord = nil, v_ord = nil, methods = [])
323
+ method_cash_clear(*methods)
324
+ o_ord, o_v_ord = get_ord, get_v_ord
325
+ ord = o_ord unless ord
326
+ result = nil
327
+
328
+ if v_ord
329
+ MIndex.set_v_ord(ord, v_ord)
330
+ MIndex.import_module(MIndex.get_module(ord || self.order, v_ord)) do
331
+ result = yield
332
+ end
333
+ MIndex.set_v_ord(o_ord, o_v_ord)
334
+ else
335
+ MIndex.import_module(MIndex.get_module(ord || self.order)) do
336
+ result = yield
337
+ end
338
+ end
339
+ result
340
+ end
341
+
342
+ def self.method_cash_clear(*m)
343
+ # $stderr.puts "method_cash_clear is given no parameter" if m.empty?
344
+ m.each do |x|
345
+ x.method_cash_clear
346
+ end
347
+ end
348
+
349
+ def method_cash_clear
350
+ @lc = @lm = @lt = @rt = @multideg = nil
351
+ end
352
+
353
+ def compact!
354
+ a = {}
355
+ each do |m, c|
356
+ a[m.compact] = c unless c.zero?
357
+ end
358
+ @bone = a
359
+ self
360
+ end
361
+
362
+ def multideg
363
+ if @multideg
364
+ @multideg
365
+ else
366
+ d = Algebra::MIndex::Unity
367
+ each do |m, c|
368
+ # d = m if !c.zero? && m > d
369
+ # d = m if !c.zero? && self.class.order.cmp(m, d) > 0 #o
370
+ d = m if !c.zero? && (m <=> d) > 0 #n
371
+ end
372
+ @multideg = d
373
+ end
374
+ end
375
+
376
+ def totdeg
377
+ if zero?
378
+ -1
379
+ else
380
+ max = 0
381
+ each do |ind, c|
382
+ unless c.zero?
383
+ t = ind.totdeg
384
+ max = t if t > max
385
+ end
386
+ end
387
+ max
388
+ end
389
+ end
390
+
391
+ def deg; multideg; end
392
+
393
+ def ==(other)
394
+ super{ |other|
395
+ each do |m, c|
396
+ return false unless c == other[m]
397
+ end
398
+ other.each do |m, c|
399
+ if !include? m
400
+ return false unless c.zero?
401
+ end
402
+ end
403
+ true
404
+ }
405
+ end
406
+
407
+ def <=>(other)
408
+ if o = regulate(other)
409
+ # THIS IS RATHER VAGUE
410
+ # lm.ind <=> o.lm.ind
411
+ # self.class.order.cmp(lm.ind, o.lm.ind) #o
412
+ lm.ind <=> o.lm.ind #n
413
+ else
414
+ x , y = other.coerce(self)
415
+ x <=> y
416
+ end
417
+ end
418
+
419
+ def +(other)
420
+ super{ |other|
421
+ a = zero
422
+ each do |m, c|
423
+ a[m] = c + other[m]
424
+ end
425
+ other.each do |m, c|
426
+ if !include? m
427
+ a[m] = self[m] + c
428
+ # a[m] = c + self[m]
429
+ end
430
+ end
431
+ a
432
+ }
433
+ end
434
+
435
+ def -(other)
436
+ super{ |other|
437
+ a = zero
438
+ each do |m, c|
439
+ a[m] = c - other[m]
440
+ end
441
+ other.each do |m, c|
442
+ if !include? m
443
+ a[m] = self[m] - c
444
+ end
445
+ end
446
+ a
447
+ }
448
+ end
449
+
450
+ def *(other)
451
+ super{ |other|
452
+ a = zero
453
+ each do |m0, c0|
454
+ other.each do |m1, c1|
455
+ a[m0 + m1] += c0 * c1
456
+ end
457
+ end
458
+ # a.compact!
459
+ a
460
+ }
461
+ end
462
+
463
+ def /(other) # other asume to be scalar
464
+ # if (o = regulate(other))
465
+ super{ |o|
466
+ if o.constant?
467
+ # self * (ground.unity / o.constant_coeff)
468
+ project{|c, ind|
469
+ c/o.constant_coeff
470
+ }
471
+ else
472
+ a, r = divmod(other)
473
+ if r.zero?
474
+ a.first
475
+ else
476
+ raise "#{other} not divides #{self}"
477
+ end
478
+ end
479
+ }
480
+ # else
481
+ # raise "other(#{o}, #{o.class}) must be monomial"
482
+ # end
483
+ end
484
+
485
+ def divmod(*f)
486
+ g = clone # not dup
487
+ f_lts = f.collect{|x| x.lt}
488
+ a = (0...f.size).collect{zero}
489
+ r = zero
490
+ until g.zero?
491
+ flag = false
492
+ f_lts.each_with_index do |f_lt, i|
493
+ g_lt = g.lt
494
+ if f_lt.divide? g_lt
495
+ d = g_lt / f_lt
496
+ if d == 0 then exit; end
497
+ a[i] += d
498
+ g = g.rt - (d * f[i]).rt
499
+ g.compact!
500
+ flag = true
501
+ break
502
+ end
503
+ end
504
+ unless flag
505
+ r += g.lt
506
+ g = g.rt #g.rt!
507
+ g.compact!
508
+ end
509
+ end
510
+ [a, r]
511
+ end
512
+
513
+ def divmod_variant(*f)
514
+ g = clone # not dup
515
+ f_lts = f.collect{|x| x.lt}
516
+ a = (0...f.size).collect{zero}
517
+ r = zero
518
+ until g.zero?
519
+ flag = false
520
+ f_lts.each_with_index do |f_lt, i|
521
+ g_lt = g.lt
522
+ if f_lt.divide? g_lt
523
+ d = g_lt / f_lt
524
+ a[i] += d
525
+ g = g.rt - (d * f[i]).rt
526
+ g.compact!
527
+ flag = true
528
+ g.zero? ? break : redo
529
+ end
530
+ end
531
+ unless flag
532
+ r += g.lt
533
+ g = g.rt #g.rt!
534
+ end
535
+ end
536
+ [a, r]
537
+ end
538
+
539
+ def %(others)
540
+ divmod(*others).last
541
+ end
542
+
543
+ def gcd(other)
544
+ fact = factorize
545
+ fact.gcd(other).pi
546
+ end
547
+
548
+ def lc
549
+ @lc ||= self[multideg]
550
+ end
551
+
552
+ def lm
553
+ #@lm ||= monomial(multideg).extend(Monomial)
554
+ monomial(multideg).extend(Monomial)
555
+ end
556
+
557
+ def lt
558
+ md = multideg
559
+ @lt ||= monomial(md, self[md]).extend(Monomial)
560
+ end
561
+
562
+ def rt
563
+ @rt ||= self - lt
564
+ end
565
+
566
+ def rt! # deepy destructive, do NOT use
567
+ @bone.delete(multideg)
568
+ method_cash_clear
569
+ self
570
+ end
571
+
572
+ def index_eval(ring, ary, ind)
573
+ e = ring.unity
574
+ ind.each_with_index do |n, i|
575
+ e *= ary[i]**n if n > 0
576
+ end
577
+ e
578
+ end
579
+
580
+ def project0(ring = self.class, ary = ring.vars)
581
+ e = ring.zero
582
+ each do |ind, c|
583
+ e += yield(c, ind)
584
+ end
585
+ e
586
+ end
587
+
588
+ alias map_to project0
589
+
590
+ def project(ring = self.class, ary = ring.vars)
591
+ e = ring.zero
592
+ each do |ind, c|
593
+ e += index_eval(ring, ary, ind) * yield(c, ind)
594
+ end
595
+ e
596
+ end
597
+
598
+ def evaluate(*ary)
599
+ project(ground, ary){|c, ind| c}
600
+ # project(self.class, ary){|c, ind| c}
601
+ end
602
+
603
+ def sub(var, value)
604
+ vs = self.class.vars
605
+ if i = vs.index(var)
606
+ vs = vs.dup
607
+ vs[i] = value
608
+ evaluate(*vs)
609
+ else
610
+ raise "#{var} is not a variable"
611
+ end
612
+ end
613
+
614
+ alias call evaluate
615
+
616
+ def derivate(v)
617
+ if an = self.class.variables.index(v) || vars.index(v)
618
+ derivate_at(an)
619
+ else
620
+ raise "#{var} is not a variable"
621
+ end
622
+ end
623
+
624
+ def derivate_at(an)
625
+ ary = vars
626
+ project0 {|c, ind|
627
+ if ind[an] < 1
628
+ zero
629
+ else
630
+ ind0 = ind - Algebra::MIndex.monomial(an)
631
+ index_eval(self.class, ary, ind0) * ind[an] * c
632
+ end
633
+ }
634
+ end
635
+
636
+ def move_const(pb, coef = ground.unity)
637
+ vs = self.class.vars.dup
638
+ a = []
639
+ vs.each_with_index do |x, i|
640
+ a << x + pb[i]*coef
641
+ end
642
+ evaluate(*a)
643
+ end
644
+
645
+ def convert_to(ring)
646
+ project(ring){|c, ind| c}
647
+ end
648
+
649
+ def need_paren_in_coeff?
650
+ if constant?
651
+ c = constant_coeff
652
+ if c.respond_to?(:need_paren_in_coeff?)
653
+ c.need_paren_in_coeff?
654
+ elsif c.is_a?(Numeric)
655
+ false
656
+ else
657
+ true
658
+ end
659
+ elsif !monomial?
660
+ true
661
+ else
662
+ false
663
+ end
664
+ end
665
+
666
+ def to_s
667
+ case self.class.display_type
668
+ when :code
669
+ pr, po = "*", "**"
670
+ when :tex
671
+ pr, po = "", "}^"
672
+ else
673
+ pr, po = "", "^"
674
+ end
675
+ a = []
676
+ # (k = keys).sort!
677
+ # k = keys.sort{|x, y| self.class.order.cmp(x, y)} #o
678
+ k = keys.sort{|x, y| x <=> y} #n
679
+ k.each do |m| c = self[m]
680
+ next if c.zero?
681
+ s = if m.unity?
682
+ c.to_s
683
+ else
684
+ case c
685
+ when Numeric
686
+ c = c == 1 ? "" : c == -1 ? "-" : c.to_s
687
+ when self.class
688
+ c = "(#{c})"
689
+ else
690
+ c = if c == 1
691
+ ""
692
+ elsif c == -1
693
+ "-"
694
+ elsif c.respond_to?(:need_paren_in_coeff?)
695
+ if c.need_paren_in_coeff?
696
+ "(#{c})"
697
+ else
698
+ c.to_s
699
+ end
700
+ elsif c.is_a?(Numeric)
701
+ c.to_s
702
+ else
703
+ "(#{c})"
704
+ end
705
+ end
706
+
707
+ ms = m.to_s(variables, pr, po)
708
+ c.empty? ? ms : c + pr + ms
709
+ end
710
+ a.unshift s
711
+ end
712
+ a.unshift "0" if a.empty?
713
+ a.join(" + ").gsub(/\+ -/, "- ")
714
+ end
715
+
716
+ alias inspect to_s unless $DEBUG
717
+
718
+ end
719
+
720
+ class MPolynomial
721
+ module Monomial# < MPolynomial
722
+ attr_reader :ind, :coeff
723
+
724
+ def self.extend_object(obj)
725
+ # p [obj, obj.class, obj.monomial?, obj == 0]
726
+ # exit unless obj.monomial?
727
+ raise "'#{obj}' must be monomial" unless obj.monomial?
728
+ super
729
+ obj.ind
730
+ obj.coeff
731
+ self
732
+ end
733
+
734
+ def ind
735
+ if defined? @ind
736
+ return @ind
737
+ else
738
+ each do |obj|
739
+ @ind = obj[0]
740
+ @coeff = obj[1]
741
+ end
742
+ return @ind
743
+ end
744
+ # return @ind if @ind
745
+ # each do |@ind, @coeff|
746
+ # return @ind
747
+ # end
748
+ raise "internal error"
749
+ end
750
+
751
+ def coeff
752
+ if @coeff
753
+ return @coeff
754
+ else
755
+ each do |obj|
756
+ @ind = obj[0]
757
+ @coeff = obj[1]
758
+ end
759
+ return @coeff
760
+ end
761
+ # return @coeff if @coeff
762
+ # each do |@ind, @coeff|
763
+ # return @coeff
764
+ # end
765
+ raise "internal error"
766
+ end
767
+
768
+ def <=>(other)
769
+ #@ind <=> other.ind
770
+ # self.class.order.cmp(@ind, other.ind) #o
771
+ @ind <=> other.ind #n
772
+ end
773
+
774
+ def divide?(other)
775
+ return true if other.zero?
776
+ case other
777
+ when Monomial
778
+ ind.devide?(other.ind) && (ground.field? ||
779
+ ground.euclidian? &&
780
+ coeff.devide?(other.coeff))
781
+ else
782
+ raise "unkown self.class #{other}(#{other.class})"
783
+ end
784
+ end
785
+
786
+ def divide_or?(other0, other1)
787
+ return true if other0.zero? && other1.zero?
788
+ if other0.is_a? Monomial and other1.is_a? Monomial
789
+ ind.devide_or?(other0.ind, other1.ind)
790
+ else
791
+ raise "unkown self.class #{other0.class}, #{other1.class}"
792
+ end
793
+ end
794
+
795
+ def prime_to?(other)
796
+ return false if other.zero?
797
+ case other
798
+ when Monomial
799
+ ind.prime_to?(other.ind)
800
+ else
801
+ raise "unkown self.class #{other}(#{other.class})"
802
+ end
803
+ end
804
+
805
+ def /(other)
806
+ case other
807
+ when self.class
808
+ self.class[(ind - other.ind), coeff / other.coeff]
809
+ else
810
+ super
811
+ end
812
+ end
813
+
814
+ def lcm(other)
815
+ monomial(ind.lcm(other.ind)).extend(Monomial)
816
+ end
817
+ end
818
+ end
819
+ end
820
+
821
+ if $0 == __FILE__
822
+ include Algebra
823
+ Foo = MPolynomial(Integer)
824
+ f = Foo[Algebra::MIndex[1,1]=>1, Algebra::MIndex[1,3]=>4, Algebra::MIndex[]=>9]
825
+ g = Foo[Algebra::MIndex[1,1]=>1, Algebra::MIndex[1,3]=>4, Algebra::MIndex[]=>9,
826
+ Algebra::MIndex[0,2,3]=>6, Algebra::MIndex[2,3]=>-1, Algebra::MIndex[2]=>-5,Algebra::MIndex[0,1]=>7]
827
+ $DEBUG = true
828
+
829
+ puts f, g, f*g
830
+
831
+ $DEBUG = false
832
+ puts
833
+
834
+ require "algebra/polynomial-converter"
835
+ require "algebra/mathn"
836
+ P = MPolynomial(Rational)
837
+ x, y, z = P.vars("xyz")
838
+ f = x**2*y + x*y**2 + y*2 + z**3
839
+ g = x*y-z**3
840
+ h = y*2-6*z
841
+
842
+ P.set_ord(:lex)
843
+ puts "LEX:"
844
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
845
+ fgh = f.divmod(g, h)
846
+ puts fgh
847
+ puts
848
+
849
+ P.method_cash_clear(f, g, h)
850
+ P.set_ord(:grlex)
851
+ puts "GRLEX:"
852
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
853
+ fgh = f.divmod(g, h)
854
+ puts fgh
855
+ puts
856
+
857
+ P.method_cash_clear(f, g, h)
858
+ P.set_ord(:grevlex)
859
+ puts "GREVLEX:"
860
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
861
+ fgh = f.divmod(g, h)
862
+ puts fgh
863
+ puts
864
+
865
+ P.variables.clear
866
+ z, y, x = P.vars("zyx")
867
+ f = x**2*y + x*y**2 + y*2 + z**3
868
+ g = x*y-z**3
869
+ h = y*2-6*z
870
+ puts "GREVLEX: order z, y, x"
871
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
872
+ fgh = f.divmod(g, h)
873
+ puts fgh
874
+ puts
875
+ end