algebra 0.2.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.
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,114 @@
1
+ # Factorization of Multivariate polynomial / Zp
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.0 (2001.09.14)
6
+
7
+ require 'algebra/m-polynomial'
8
+ require 'algebra/polynomial'
9
+ require 'algebra/polynomial-factor'
10
+ require 'algebra/residue-class-ring'
11
+ require 'algebra/chinese-rem-th'
12
+ require 'algebra/m-polynomial-gcd'
13
+ # require "algebra/annihilate"
14
+
15
+ module Algebra
16
+ module MPolynomialFactorization
17
+ # include PolynomialFactorization::Z
18
+
19
+ def factorize_modp(an = 0)
20
+ f = self
21
+ f = f.sqfree_zp if an == 0
22
+ an += 1 while f.deg_at(an) <= 0
23
+ f = f.pp(an)
24
+ lc_of_f = f.lc_at(an)
25
+ f = f.monic_int(an)
26
+ facts = f._factorize(an)
27
+ facts = facts.map! do |f2|
28
+ f3 = f2.project(self.class) { |c, j| c * lc_of_f**j[an] }
29
+ f3.pp(an)
30
+ end
31
+ facts = facts.fact_all_u(self)
32
+ facts.mcorrect_lc!(self, an) do |fac|
33
+ fac.factorize_modp(an + 1)
34
+ end
35
+ facts
36
+ end
37
+
38
+ def verschiebung
39
+ ary = vars
40
+ ch = ground.char
41
+ e = zero
42
+ project0 do |c, ind|
43
+ c * index_eval(self.class, ary, ind.collect { |i| i / ch })
44
+ end
45
+ end
46
+
47
+ def sqfree_zp
48
+ f = self
49
+ s = unity
50
+ until f.constant?
51
+ g = f._sqfree
52
+ s *= g
53
+ f = (f / g).verschiebung
54
+ end
55
+ s / s.lc
56
+ end
57
+
58
+ # def hensel_lift_zp(g0, f0, char, height)
59
+ def hensel_lift_zp(g0, f0, char, height, where)
60
+ # self in MPolynomial/int
61
+ # g0 in Polyomial/Zp, candidate of factor of f0
62
+ # f0 in Polyomial/Zp, one variable reduction of self
63
+
64
+ # fk = _hensel_lift(g0, f0, char, height) {|ha, ary, cofacts|
65
+ fk = _hensel_lift(g0, f0, char, height, where) do |ha, ary, cofacts|
66
+ decompose_on_cofactors_modp(ha, ary, cofacts)
67
+ end
68
+
69
+ r = self - fk[0] * fk[1]
70
+ return fk if r.zero?
71
+
72
+ nil
73
+ end
74
+ end
75
+ end
76
+
77
+ if __FILE__ == $PROGRAM_NAME
78
+ require 'algebra/rational'
79
+ require 'algebra/m-polynomial-factor'
80
+ include Algebra
81
+
82
+ def test(f)
83
+ print "#{f}\n => "
84
+ a = f.factorize_modp
85
+ sw = (f == a.pi)
86
+ puts a.inspect.to_s, sw.to_s
87
+ puts
88
+ raise unless sw
89
+ end
90
+
91
+ # P = MPolynomial(Rational)
92
+ Z7 = ResidueClassRing(Integer, 7)
93
+ P = MPolynomial(Z7)
94
+ # PS = Polynomial(Z7, "t")
95
+ x, y, z = P.vars('xyz')
96
+ # x, y, z, t = P.vars("xyzt")
97
+
98
+ fs = [
99
+ x**3 + y**3 + z**3 - 3 * x * y * z,
100
+ (x + y + 1)**2 * x,
101
+ (x + y + 1)**2 * (x + 1),
102
+ x**2 + (-z**2 - y * z + y + z + 2) * x + (y * z**3 - z**3 - y**2 * z - y * z + 2 * z),
103
+ (x + z + 1) * (x + y) * (x + y**2 + z + 2),
104
+ (x + z + 1) * (x + y) * (x + y**2 + z),
105
+ (x + z + 1) * (x + y)**2 * (x + y**2 + z + 2),
106
+ (x + y) * (y + z) * (z + x),
107
+ (x + y) * (y + z) * (z + x)**3,
108
+ (x * y + 1) * (x * z + 1),
109
+ # (t + x)*(t + y)*(t + z),
110
+ ]
111
+ fs.each do |f|
112
+ test(f)
113
+ end
114
+ end
@@ -0,0 +1,315 @@
1
+ # Factorization of Multivariate polynomial
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.0 (2001.09.14)
6
+
7
+ require 'algebra/factors'
8
+ require 'algebra/chinese-rem-th'
9
+ require 'algebra/m-polynomial-factor-int'
10
+ require 'algebra/m-polynomial-factor-zp'
11
+ require 'algebra/combinatorial'
12
+
13
+ module Algebra
14
+ module MPolynomialFactorization
15
+ include ChineseRemainderTheorem
16
+
17
+ def each_point_int(n0, na)
18
+ # obscure algorithm
19
+ pblock = 7
20
+ m = 0
21
+ loop do
22
+ each_point_zp(n0, na, m + pblock) do |pb0|
23
+ next if (1...n0 - na).find { |k| pb0[na + k] < m }
24
+ yield pb0
25
+ end
26
+ m += pblock
27
+ $stderr.puts "warning (each_point_int): it's hard to find adequate zero point"
28
+ end
29
+ end
30
+
31
+ def each_point_zp(n0, na, char)
32
+ avoid_indice = indice_of_constant
33
+ Combinatorial.power_cubic(char, n0 - na - 1) do |a|
34
+ pb0 = (0..na).collect { 0 } + a
35
+ next if avoid_indice.find { |i| !pb0[i].zero? }
36
+ yield(pb0)
37
+ end
38
+ raise 'each_point(limit over)'
39
+ end
40
+
41
+ def _factorize(na = 0)
42
+ pring = Algebra.Polynomial(ground, 'x')
43
+
44
+ f = self
45
+ f_one = nil
46
+ pb0 = nil
47
+ # f : m-poly. moved by pb0 reduced onto f_one
48
+ # f_one : sqfree poly.
49
+ # pb0 : parallel moving vector
50
+
51
+ if ground == Integer
52
+ each_point_int(vars.size, na) do |pb0_dash|
53
+ pb0 = pb0_dash
54
+ f = move_const(pb0) if pb0.find { |x| !x.zero? }
55
+ f_one = f.reduce2onevar(pring, na)
56
+ break if f_one.psqfree?
57
+ end
58
+ fact_one, char = f_one._factorize
59
+ hensel = :hensel_lift_int
60
+ else # ground == Zp
61
+ char = ground.char
62
+ each_point_zp(vars.size, na, char) do |pb0_dash|
63
+ pb0 = pb0_dash
64
+ f = move_const(pb0) if pb0.find { |x| !x.zero? }
65
+ f_one = f.reduce2onevar(pring, na)
66
+ break if f_one.sqfree?
67
+ end
68
+ fact_one = f_one.factorize_modp
69
+ hensel = :hensel_lift_zp
70
+ end
71
+
72
+ factors = Factors.new
73
+ if fact_one.fact_size <= 1
74
+ factors *= self
75
+ return factors
76
+ end
77
+ height = totdeg_away_from(0)
78
+
79
+ f1 = f
80
+ fact_one.each_product do |g0|
81
+ f1_one = f1.reduce2onevar(pring, na)
82
+ next if g0.deg > f1_one.deg
83
+ # fact_q = f1.send(hensel, g0, f1_one, char, height)
84
+ fact_q = f1.send(hensel, g0, f1_one, char, height, na)
85
+ next unless fact_q
86
+ # if fact_q = f1.hensel_lift(g0, f1_one, char, height)
87
+ f0, f1 = fact_q
88
+ factors.push [f0, 1]
89
+ break if f1.totdeg <= 0
90
+ true
91
+ end
92
+
93
+ factors.collect { |f3, i| [f3.move_const(pb0, -1), i] }
94
+ end
95
+
96
+ # def _hensel_lift(g0, f0, char, height)
97
+ def _hensel_lift(g0, f0, _char, height, where)
98
+ # self in MPolynomial/ZorZp
99
+ # g0 in Polyomial/ZorZp, candidate of factor of f0
100
+ # f0 in Polyomial/ZoZzp, one variable reduction of self
101
+
102
+ ring = self.class
103
+ ring_one = g0.class
104
+
105
+ h0, r0 = f0.divmod g0
106
+ raise 'each_product does not work well' unless r0.zero?
107
+
108
+ # where = 0
109
+ ary = [g0, h0]
110
+ cofacts = mk_cofacts(ary)
111
+ fk = ary.collect { |fx| fx.value_on_one(ring, where) } # MPolynomial
112
+
113
+ height.times do |k|
114
+ c = self - fk[0] * fk[1]
115
+ h = c.annihilate_away_from(where, k + 1)
116
+ h_alpha0 = h.collect_away_from(where, ring_one) # Hash: ind0=>Polynomial
117
+ h_alpha = {}
118
+
119
+ h_alpha0.each do |ind, ha|
120
+ h_alpha[ind] = yield(ha, ary, cofacts)
121
+ end
122
+
123
+ hias = ary.collect { {} }
124
+ h_alpha.each do |ind, ha_i|
125
+ ha_i.each_with_index do |fx, i|
126
+ next if fx.zero?
127
+ hias[i][ind] = fx
128
+ end
129
+ end
130
+
131
+ hi = hias.collect do |hia|
132
+ e = ring.zero
133
+ hia.each do |ind, fx|
134
+ e += ring.monomial(ind) * fx.value_on_one(ring, where)
135
+ end
136
+ e
137
+ end
138
+ fk_new = []
139
+ hi.each_with_index do |fx, i|
140
+ fk_new.push fk[i] + fx
141
+ end
142
+ fk = fk_new
143
+ end
144
+ fk
145
+ end
146
+
147
+ def _sqfree
148
+ dvs = []
149
+ vars.each_with_index do |_v, i|
150
+ dv = derivate_at(i)
151
+ next if dv.zero?
152
+ dvs.push dv
153
+ end
154
+ g = gcd_all(*dvs)
155
+ self / g
156
+ end
157
+
158
+ def pp(an)
159
+ x, *a = coeffs_at(an)
160
+ content = x.gcd_all(*a)
161
+ self / content
162
+ end
163
+
164
+ def monic_int(na = 0)
165
+ d = deg_at(na)
166
+ a = lc_at(na)
167
+ ary = self.class.vars
168
+ m = project0(self.class) do |c, ind|
169
+ n = ind[na]
170
+ if n == d
171
+ zero
172
+ elsif n < d
173
+ c * a**(d - n - 1) * index_eval(self.class, ary, ind)
174
+ elsif c.zero?
175
+ zero
176
+ else
177
+ raise 'fatal contradiction!'
178
+ end
179
+ end
180
+
181
+ index_eval(self.class, ary, MIndex.monomial(na, d)) + m
182
+ end
183
+ end
184
+
185
+ class MPolynomial
186
+ include MPolynomialFactorization
187
+
188
+ def factorize
189
+ return Algebra::Factors.new([[zero, 1]]) if zero?
190
+ fact = if ground <= Integer
191
+ factorize_int
192
+ elsif defined?(Rational) && ground <= Rational ||
193
+ defined?(LocalizedRing) && ground <= LocalizedRing
194
+ factorize_rational
195
+ elsif defined?(ResidueClassRing) && ground <= ResidueClassRing && ground.ground <= Integer
196
+ factorize_modp
197
+ else
198
+ factorize_alg
199
+ end
200
+ fact.normalize!
201
+ end
202
+
203
+ def reduce2onevar(pring, n)
204
+ evar = []
205
+ self.class.vars.each_with_index do |_v, i|
206
+ evar.push i == n ? pring.var : pring.zero
207
+ end
208
+ project(pring, evar) { |c, _ind| c }
209
+ end
210
+
211
+ def annihilate_away_from(n, e = 0)
212
+ # n = 0, e = 2
213
+ # x*y*z + x*y**2*z + x*y*z + y*z + z**3 #=> x*y*z + y*z + z**3
214
+ project(self.class) do |c, ind|
215
+ ind.totdeg - ind[n] > e ? ground.zero : c
216
+ end
217
+ end
218
+
219
+ def deg_at(an)
220
+ if zero?
221
+ -1
222
+ else
223
+ max = 0
224
+ each do |ind, c|
225
+ unless c.zero?
226
+ t = ind[an]
227
+ max = t if t > max
228
+ end
229
+ end
230
+ max
231
+ end
232
+ end
233
+
234
+ def indice_of_constant
235
+ (0...vars.size).find_all { |an| deg_at(an) <= 0 }
236
+ end
237
+
238
+ def lc_at(an)
239
+ d = deg_at(an)
240
+ s = zero
241
+ each do |ind, c|
242
+ next if c.zero?
243
+ if ind[an] == d
244
+ md = ind.annihilate(an)
245
+ s += monomial(md, c)
246
+ end
247
+ end
248
+ s
249
+ end
250
+
251
+ def coeffs_at(an)
252
+ ss = (0..deg_at(an)).collect { zero }
253
+ each do |ind, c|
254
+ next if c.zero?
255
+ md = ind.annihilate(an)
256
+ ss[ind[an]] += monomial(md, c)
257
+ end
258
+ ss
259
+ end
260
+
261
+ def totdeg_away_from(n)
262
+ max = 0
263
+ each do |ind, c|
264
+ next if c.zero?
265
+ m = ind.totdeg - ind[n]
266
+ max = m if m > max
267
+ end
268
+ max
269
+ end
270
+
271
+ def collect_away_from(n, ps)
272
+ # 2*x*y*z + x**2*y*z + x*y #=> [y*z=>(2*x + x**2), y=>x]
273
+ h_alpha = {}
274
+ each do |ind, c|
275
+ next if c.zero?
276
+ i = ind[n]
277
+ ind0 = ind.annihilate(n)
278
+ v = ps.var
279
+ h_alpha[ind0] = h_alpha[ind0] ? h_alpha[ind0] + c * v**i : c * v**i
280
+ end
281
+ h_alpha
282
+ end
283
+ end
284
+
285
+ class Polynomial
286
+ def value_on_one(ring, n = 0)
287
+ e = ring.zero
288
+ x = ring.vars[n]
289
+ reverse_each do |c|
290
+ e = e * x + c
291
+ end
292
+ e
293
+ end
294
+ end
295
+ end
296
+
297
+ if __FILE__ == $PROGRAM_NAME
298
+ require 'algebra/residue-class-ring'
299
+ require 'algebra/m-polynomial'
300
+ include Algebra
301
+ Z7 = ResidueClassRing(Integer, 7)
302
+ P = MPolynomial(Z7)
303
+ x, y, z = P.vars('xyz')
304
+ # f = x**2*y*z + (-z**2 - y*z + y + z + 2)*x + (y*z**3 - z**3 - y**2*z - y*z + 2*z)
305
+ # f = x**2*y + x**2*z + x * y * z
306
+ # f = x**2*y + x**2*z + x * y
307
+ f = (x + y) * (y + z) * (z + x)
308
+
309
+ # p f.lc_at(0)
310
+ p f
311
+ # p f.monic_int
312
+ p f.coeffs_at(0)
313
+ p((x * x + y + 1 + x * z + z * 2).indice_of_constant)
314
+ p(x.indice_of_constant)
315
+ end
@@ -0,0 +1,40 @@
1
+ require 'algebra/polynomial'
2
+ require 'algebra/m-polynomial'
3
+ # require "algebra/polynomial-converter"
4
+
5
+ module Algebra
6
+ class MPolynomial
7
+ def gcd(other)
8
+ pring = self.class.convert_to(Polynomial)
9
+ f = value_on(pring)
10
+ g = other.value_on(pring)
11
+ h = f.gcd_rec(g)
12
+ k = h.value_on(self.class)
13
+ k
14
+ end
15
+
16
+ def gcd_all(*a)
17
+ t = self
18
+ a.each do |x|
19
+ break if t.unit?
20
+ t = t.gcd(x)
21
+ end
22
+ t
23
+ end
24
+ end
25
+ end
26
+
27
+ if $PROGRAM_NAME == __FILE__
28
+ require 'algebra/residue-class-ring'
29
+ include Algebra
30
+ Z7 = ResidueClassRing(Integer, 7)
31
+ P = MPolynomial(Z7)
32
+ # P = MPolynomial(Integer)
33
+ x, y, z = P.vars('xyz')
34
+
35
+ f = (x + y) * (x + 2 * y)
36
+ g = (x + 2 * y) * (x + 3 * y)
37
+ # f, g = x**2*y, x*y**2
38
+ p k = f.gcd(g)
39
+ p k / 3 == x + 2 * y
40
+ end