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,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