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,148 @@
1
+ # Factorization of Polyomial over Algebraic Extension over Rational
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.0 (2001.04.17)
6
+
7
+ # require "algebra/polynomial-converter"
8
+ require 'algebra/algebraic-extension-field'
9
+
10
+ module Algebra
11
+ class Polynomial
12
+ module Alg
13
+ def norm
14
+ f = project(Algebra.Polynomial(ground.ground, variable)) { |c, _i| c.lift }
15
+ f.var_swap.resultant(ground.modulus)
16
+ end
17
+ end
18
+ include Alg
19
+
20
+ def factorize_alg_old
21
+ # if !respond_to?(:deg) or deg <= 1
22
+ return Algebra::Factors.new([[self, 1]]) if deg <= 1
23
+
24
+ t = ground.var
25
+ x = var
26
+ sf = sqfree.monic
27
+
28
+ n = 0
29
+ loop do
30
+ nm = sf.norm
31
+ break if nm.sqfree?
32
+ n += 1
33
+ sf = sf.evaluate(x - t)
34
+ end
35
+ fac = nm.factorize
36
+ fac.map! do |f0|
37
+ f0.convert_to(self.class).gcd(sf).evaluate(x + t * n).monic
38
+ end
39
+ fac.fact_all(self).correct_lc!(self)
40
+ end
41
+
42
+ def factorize_alg(s = 0)
43
+ return Algebra::Factors.new([[self, 1]]) if deg <= 1
44
+
45
+ t = ground.var
46
+ x = var
47
+ sf = sqfree.monic
48
+
49
+ nm = sf.evaluate(x - t * s).norm
50
+ fac0 = Algebra::Factors.new
51
+ nm.factorize.each do |f0, n|
52
+ next if f0.deg <= 0
53
+ g = f0.convert_to(self.class).evaluate(x + t * s)
54
+ g = g.gcd(sf).monic
55
+ if n == 1
56
+ fac0.multiply g
57
+ elsif n >= 2
58
+ h = g.factorize_alg(s + 1)
59
+ fac0.concat h
60
+ end
61
+ end
62
+ fac0.fact_all(self).correct_lc!(self)
63
+ end
64
+ end
65
+ end
66
+
67
+ if __FILE__ == $PROGRAM_NAME
68
+ def test(f, s = '')
69
+ print "#{f}#{s}\n"
70
+ a = f.factorize
71
+ sw = (f == a.pi)
72
+ puts "#{a.inspect}, #{sw}"
73
+ raise unless sw
74
+ end
75
+
76
+ require 'algebra/polynomial'
77
+ require 'algebra/polynomial-factor'
78
+ require 'algebra/residue-class-ring'
79
+ require 'algebra/rational'
80
+
81
+ n, i, j, k = ARGV.collect(&:to_i)
82
+ fss = [
83
+ 'x**4 + 1', # 0
84
+ 'x**2 + x + 1', # 1
85
+ 'x**4 + 1 + a', # 2
86
+ '(x**4 + 1)*(x**2 + x + 1)', # 3
87
+ 'x**4 + 4', # 4
88
+ 'x**2 + 4*x + 1', # 5
89
+ 'x**2 + 1', # 6
90
+ 'x**3 - 1', # 7
91
+ 'x**3 - 2', # 8
92
+ ]
93
+ fs = fss[n || 0]
94
+ ass = [
95
+ 'a**2 + 1', # 0
96
+ 'a**2 - 2', # 1
97
+ 'a**3 - 2', # 2
98
+ 'a**2 - 3', # 3
99
+ ]
100
+ bss = [
101
+ 'b**2 - 2', # 0
102
+ 'b**3 - 2', # 1
103
+ 'b**2 + b + 1', # 2
104
+ 'b**2 + 1', # 3
105
+ 'b**2 - 3', # 4
106
+ ]
107
+ css = [
108
+ 'c**3 - 2', # 0
109
+ 'c**2 - 3', # 1
110
+ ]
111
+
112
+ as = ass[i || 0]
113
+ bs = bss[j || 0]
114
+ cs = css[k || 0]
115
+
116
+ if i
117
+ ka = Algebra.AlgebraicExtensionField(Rational, 'a') { |_a| eval as }
118
+ # a = ka.var
119
+ if j
120
+ kab = Algebra.AlgebraicExtensionField(ka, 'b') { |_b| eval bs }
121
+
122
+ if k
123
+ kabc = Algebra.AlgebraicExtensionField(kab, 'c') { |_c| eval cs }
124
+ pkabc = Algebra.Polynomial(kabc, 'x')
125
+ x = pkabc.var
126
+ f = eval fs
127
+ test(f, ", in Q[a, b, c, x]/(#{as}, #{bs}, #{cs})")
128
+ else
129
+ pkab = Algebra.Polynomial(kab, 'x')
130
+ x = pkab.var
131
+ f = eval fs
132
+ test(f, ", in Q[a, b, x]/(#{as}, #{bs})")
133
+ end
134
+ else
135
+ pka = Algebra.Polynomial(ka, 'x')
136
+ x = pka.var
137
+ f = eval fs
138
+ test(f, ", in Q[a, x]/(#{as})")
139
+ end
140
+ else
141
+ [fss, ass, bss, css].each do |xs|
142
+ puts '-----------'
143
+ xs.each_with_index do |f1, i1|
144
+ puts "#{i1}: #{f1}"
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,252 @@
1
+ # Factorization of Polyomial over Integer by Zassenhaus's method
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.0 (2001.04.19)
6
+
7
+ require "algebra/prime-gen"
8
+ require "algebra/residue-class-ring"
9
+
10
+ module Algebra
11
+ module PolynomialFactorization
12
+ module Z
13
+ def resolve_c(g, h, c) # find [a, b] s.t. a * g + b * h == c
14
+ d, a, b = g.gcd_coeff(h)
15
+ q, r = c.divmod(d)
16
+ raise "#{c} is not devided by (#{g}, #{h})" unless r.zero?
17
+ a = a * q
18
+ b = b * q
19
+ q, r = a.divmod(h)
20
+ a = r #= a - q * h
21
+ b = b + q * g
22
+ [a, b]
23
+ end
24
+
25
+ def centorize(f, n)
26
+ half = n / 2
27
+ f.class.new(*f.collect{|c| c > half ? c - n : c })
28
+ end
29
+
30
+ def try_e(g, u)
31
+ m = g.deg
32
+ c = 1.0
33
+ n = (m/2).to_i
34
+ 0.upto n - 1 do |i|
35
+ c *= (m - i) / (n - i)
36
+ end
37
+ s = 0
38
+ each do |c|
39
+ s += c**2
40
+ end
41
+ (Math.log(c * Math.sqrt(s))/Math.log(u)).to_i + 1
42
+ end
43
+
44
+ def sqfree_over_integral
45
+ f = pp
46
+ g = f.derivate.pp
47
+ h = f.pgcd(g)
48
+ f / h.pp
49
+ end
50
+
51
+ def divmod_ED(o) # divmod in the ring over Euclidian Domain
52
+ raise ZeroDivisionError, "divisor is zero" if o.zero?
53
+
54
+ d0, d1 = deg, o.deg
55
+ if d1 <= 0
56
+ a = collect{|c|
57
+ q, r = (ground.field? ? [ground.zero, c/o.lc] : c.divmond(o.lc))
58
+ if r.zero?
59
+ [q, zero]
60
+ else
61
+ return [zero, self]
62
+ end
63
+ }
64
+ [self.class.new(*a), zero]
65
+ elsif d0 < d1
66
+ [zero, self]
67
+ else
68
+ q, r = (ground.field? ? [lc/o.lc, ground.zero] : lc.divmod(o.lc))
69
+ if r.zero?
70
+ tk = monomial(d0 - d1) * q
71
+ e = rt - o.rt * tk
72
+ q, r = e.divmod_ED(o)
73
+ [q + tk, r]
74
+ else
75
+ [zero, self]
76
+ end
77
+ end
78
+ end
79
+
80
+ def resultant_by_elimination(o) #ground ring must be a field
81
+ sylvester_matrix(o).determinant_by_elimination
82
+ end
83
+
84
+ def reduce_over_prime_field(f)
85
+ Primes.new.each do |prime|
86
+ if prime > 10
87
+ pf = Algebra::Polynomial.reduction(Integer, prime, "x")
88
+ f0 = pf.reduce(f)
89
+ r = f0.resultant_by_elimination(f0.derivate)
90
+ unless r.zero?
91
+ return f0
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ def lifting(f, ring)
98
+ f.project(ring){|c, i| c.lift}
99
+ end
100
+
101
+ def hensel_lift(g0)
102
+ ring, pf, char = self.class, g0.class, g0.class.ground.char
103
+
104
+ f0 = pf.reduce(self)
105
+ h0, r0 = f0.divmod g0
106
+ unless r0.zero?
107
+ raise "each_product does not work well"
108
+ #return nil
109
+ end
110
+
111
+ g = lifting(g0, ring)
112
+ h = lifting(h0, ring)
113
+ a, b = 0, 0
114
+
115
+ 0.upto try_e(g, char) do |e|
116
+ mod = char ** e
117
+ mod1 = mod * char
118
+ g = centorize(g + b * mod, mod1)
119
+ h = centorize(h + a * mod, mod1)
120
+
121
+ q, r = divmod(g)
122
+ if r.zero?
123
+ return [g, q]
124
+ end
125
+
126
+ c = (self - g * h) / mod1
127
+ g0, h0, c0 = pf.reduce(g), pf.reduce(h), pf.reduce(c)
128
+ a0, b0 = resolve_c(g0, h0, c0)
129
+ a, b = lifting(a0, ring), lifting(b0, ring)
130
+ end
131
+
132
+ return nil
133
+ end
134
+
135
+ def _factorize
136
+ if constant?
137
+ return Algebra::Factors.new([[self, 1]]), 0
138
+ end
139
+ f = sqfree_over_integral
140
+ flc = f.lc
141
+ f = f.monic_int(flc)
142
+
143
+ f0 = reduce_over_prime_field(f)
144
+ fa = f0.factorize_modp
145
+
146
+ f1 = f
147
+ factors = Algebra::Factors.new
148
+ # fa.each_product0 do |g0|
149
+ fa.each_product do |g0|
150
+ next if g0.deg > f1.deg
151
+ # if fact_q = f1.hensel_lift(g0, f0.class)
152
+ if fact_q = f1.hensel_lift(g0)
153
+ fact, f1 = fact_q
154
+ factors.push [fact, 1]
155
+ break if f1.deg <= 0
156
+ true
157
+ end
158
+ end
159
+
160
+ factors.map!{|f2| f2.project(self.class){|c, j| c*flc**j}.pp }
161
+ facts = factors.fact_all(self)
162
+ [facts.correct_lc!(self), f0.ground.char]
163
+ end
164
+
165
+ def factorize_int
166
+ _factorize.first
167
+ end
168
+ end
169
+
170
+ module Q
171
+ def contQ
172
+ ns = collect{|q| q.numerator}
173
+ ds = collect{|q| q.denominator}
174
+ n = ns.first.gcd_all(* ns[1..-1])
175
+ d = ds.first.lcm_all(* ds[1..-1])
176
+ # ground.new(n, d)
177
+ if ground == Rational #in 1.8.0, Rational.new is private.
178
+ Rational(n, d)
179
+ else
180
+ raise "unknown gound type #{ground}" #20030606
181
+ ground.new(n, d)
182
+ end
183
+ end
184
+
185
+ def ppQ(ring)
186
+ (self / contQ).project(ring){|c, j| c.to_i}
187
+ end
188
+
189
+ def factorize_rational
190
+ pz = Algebra.Polynomial(Integer, "x")
191
+ fz = ppQ(pz)
192
+ a = fz.factorize
193
+ u = ground.ground.unity # ground == Rational, ground.ground == Integer
194
+ b = a.collect{|f, i|
195
+ [f.project(self.class){|c, j|
196
+ # ground.new
197
+ ##in 1.8.0, Rational.new is private.
198
+ ground == Rational ? Rational(c, u) : Rational(c, u)
199
+ }, i]
200
+ }
201
+ contQ == ground.unity ? b : b.unshift([self.class.const(contQ), 1])
202
+ end
203
+ end
204
+
205
+ include Z
206
+ include Q
207
+ end
208
+ end
209
+
210
+ if __FILE__ == $0
211
+ require "algebra/polynomial"
212
+ require "algebra/polynomial-factor"
213
+ require "algebra/residue-class-ring"
214
+ require "algebra/rational"
215
+ # include Algebra
216
+
217
+ def test(f)
218
+ print "#{f}\n => "
219
+ a = f.factorize
220
+ sw = (f == a.pi)
221
+ puts "#{a.inspect}, #{sw}"
222
+ raise "Test Failed" unless sw
223
+ end
224
+
225
+ PQ = Algebra.Polynomial(Rational, "y")
226
+ y = PQ.var
227
+
228
+ P = Algebra.Polynomial(Integer, "x")
229
+ x = P.var
230
+
231
+ _h = x**12 - 12*x**10 - 4*x**9 + 96*x**8 - 442*x**6 + 672*x**5 + 1572*x**4 - 1412*x**3 - 2544*x**2 - 1560*x + 4225
232
+
233
+ fs = [
234
+ 54*x**3 + 57*x**2 + 28*x + 15, #(9*x**2+2*x+3)*(6*x+5)
235
+ (x**2+x+1)**2*(x+1)**3,
236
+ (x**2+x+1)**2,
237
+ (x**2+x+1)*(x+1)**3,
238
+ (x**2+x+1)*(x+1)*(x+2),
239
+ (x**2+x+1)*(x+1),
240
+ (x**2+x+1),
241
+ (x+1)**3,
242
+ (3*x + 1)*(2*x + 5)*3,
243
+ (x**3 + 1)**3,
244
+ # (x**8+x**6+x**5+x**4+x**3+x**2+1)*(x**2+x+1)**3,
245
+ (y**2 + 2*y + Rational(3, 4))*(y + Rational(1, 3)),
246
+ # h
247
+ ]
248
+ # fs[-1..-1].each do |f|
249
+ fs.each do |f|
250
+ test(f)
251
+ end
252
+ end
@@ -0,0 +1,165 @@
1
+ # Factorization of Polyomial over Zp by Berlekamp's method
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.0 (2001.04.17)
6
+
7
+ require "algebra/matrix-algebra"
8
+ require "algebra/gaussian-elimination"
9
+
10
+ module Algebra
11
+ module PolynomialFactorization
12
+ module Zp
13
+ def verschiebung
14
+ x = var
15
+ ch = ground.char
16
+ e = ground.zero
17
+ each_with_index do |c, i|
18
+ e += x ** (i/ch) * c
19
+ end
20
+ e
21
+ end
22
+
23
+ def weak_factors_and_r
24
+ #self asumed to be square and p- free
25
+ y = var ** ground.char
26
+ n = deg
27
+
28
+ u = Algebra.SquareMatrix(ground, n).collect_column{|i|
29
+ a = y ** i % self
30
+ (0...n).collect{|j| a[j]}
31
+ }
32
+
33
+ u -= u.unity
34
+
35
+ basis = u.kernel_basis
36
+
37
+ wf = []
38
+ basis.each_with_index do |h, i|
39
+ # next if i == 0
40
+ fh = self.class.new(*h)
41
+ (0...ground.char).each do |s|
42
+ fhg = (fh - s).gcd(self)
43
+ if fhg.deg > 0
44
+ fhgm = fhg / fhg.lc
45
+ wf.push(fhgm) unless wf.include? fhgm
46
+ end
47
+ end
48
+ end
49
+ [wf, basis.size]
50
+ end
51
+
52
+ def factors_of_sqfree
53
+ #self assumed to be square and p-free
54
+ wf, fact_size = weak_factors_and_r
55
+ n = deg
56
+ degwize = (1..n).collect{|i| []}
57
+ wf.each do |f|
58
+ degwize[f.deg-1].push f
59
+ end
60
+ degwize.each_with_index do |a, i|
61
+ (i..degwize.size-1).each do |j|
62
+ b = degwize[j]
63
+ a.each do |f|
64
+ b.each do |g|
65
+ next if f == g
66
+ h = f.gcd(g)
67
+ if h.deg > 0 && h.deg < f.deg
68
+ h = h / h.lc
69
+ unless degwize[h.deg-1].include? h
70
+ degwize[h.deg-1].push(h)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ facts = []
79
+ degwize.each_with_index do |a, i|
80
+ b = []
81
+ a.each do |f|
82
+ b.push f unless facts.find{|g| g.divide?(f)}
83
+ end
84
+ facts.concat b
85
+ break if facts.size == fact_size
86
+ end
87
+ facts
88
+ end
89
+
90
+ #module_function :verschiebung, :weak_factors_and_r, :factors_of_sqfree, :factorize
91
+
92
+ def factorize_modp
93
+ me = self
94
+ g = sqfree
95
+ fs = Factors.new
96
+ g.factors_of_sqfree.each do |f|
97
+ i, r = 0, 0
98
+ while me.deg > 0
99
+ q, r = me.divmod f
100
+ if r.zero?
101
+ me = q
102
+ i += 1
103
+ else
104
+ break
105
+ end
106
+ end
107
+ fs.push [f, i]
108
+ end
109
+
110
+ # for 'over Zp'
111
+ if ch = ground.char
112
+ if me.deg > 0
113
+ me.verschiebung.factorize_modp.each do |f_i|
114
+ f0, i0 = f_i
115
+ fs.push [f0, i0*ch]
116
+ end
117
+ end
118
+ end
119
+ fs
120
+ end
121
+ # module_function :factorize_modp
122
+
123
+ #def _factorize
124
+ # [factorize_modp, ground.char]
125
+ #end
126
+ end
127
+
128
+ include Zp
129
+ end
130
+ end
131
+
132
+ if __FILE__ == $0
133
+ # include Algebra
134
+ def test(f)
135
+ print "#{f}\n => "
136
+ a = f.factorize
137
+ sw = (f == a.pi)
138
+ puts "#{a.inspect}, #{sw}"
139
+ raise unless sw
140
+ end
141
+
142
+ require "algebra/polynomial"
143
+ require "algebra/polynomial-factor"
144
+ require "algebra/residue-class-ring"
145
+ require "algebra/rational"
146
+ PQ = Algebra.Polynomial(Rational, "x")
147
+
148
+ [2, 3, 5, 7, 11].each do |n|
149
+ puts "mod = #{n}"
150
+ fn = Algebra.ResidueClassRing(Integer, n)
151
+ pfn = Algebra.Polynomial(fn, "y")
152
+
153
+ _y = pfn.var
154
+ x = PQ.var
155
+ fs = [
156
+ x**2+x+1,
157
+ (x**2+x+1)*(x+1)**3,
158
+ (x**8+x**6+x**5+x**4+x**3+x**2+1)*(x**2+x+1)**3
159
+ ]
160
+ fs.each do |f|
161
+ g = f.project(pfn) {|c, i| fn[c.mod(n)]}
162
+ test(g)
163
+ end
164
+ end
165
+ end