algebra 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +53 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +21 -0
- data/README-ja.txt +60 -0
- data/README.md +61 -0
- data/Rakefile +43 -0
- data/algebra.gemspec +33 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/doc-ja/README-ja.html +69 -0
- data/doc-ja/README-ja.rd +60 -0
- data/doc-ja/README.html +0 -0
- data/doc-ja/README.rd +0 -0
- data/doc-ja/algebra-ja.html +66 -0
- data/doc-ja/algebra-ja.rd +60 -0
- data/doc-ja/algebraic-equation-ja.html +36 -0
- data/doc-ja/algebraic-equation-ja.rd +26 -0
- data/doc-ja/algebraic-extension-field-ja.html +122 -0
- data/doc-ja/algebraic-extension-field-ja.rd +118 -0
- data/doc-ja/algebraic-parser-ja.html +87 -0
- data/doc-ja/algebraic-parser-ja.rd +95 -0
- data/doc-ja/changes.html +161 -0
- data/doc-ja/changes.rd +119 -0
- data/doc-ja/elementary-divisor-ja.html +56 -0
- data/doc-ja/elementary-divisor-ja.rd +45 -0
- data/doc-ja/euclidian-ring-ja.html +78 -0
- data/doc-ja/euclidian-ring-ja.rd +69 -0
- data/doc-ja/finite-group-ja.html +285 -0
- data/doc-ja/finite-group-ja.rd +276 -0
- data/doc-ja/finite-map-ja.html +224 -0
- data/doc-ja/finite-map-ja.rd +227 -0
- data/doc-ja/finite-set-ja.html +393 -0
- data/doc-ja/finite-set-ja.rd +408 -0
- data/doc-ja/index-ja.html +113 -0
- data/doc-ja/index-ja.rd +112 -0
- data/doc-ja/jordan-form-ja.html +106 -0
- data/doc-ja/jordan-form-ja.rd +99 -0
- data/doc-ja/localized-ring-ja.html +121 -0
- data/doc-ja/localized-ring-ja.rd +131 -0
- data/doc-ja/m-polynomial-ja.html +542 -0
- data/doc-ja/m-polynomial-ja.rd +596 -0
- data/doc-ja/matrix-algebra-ja.html +686 -0
- data/doc-ja/matrix-algebra-ja.rd +727 -0
- data/doc-ja/matrix-algebra-triplet-ja.html +124 -0
- data/doc-ja/matrix-algebra-triplet-ja.rd +129 -0
- data/doc-ja/permutation-group-ja.html +159 -0
- data/doc-ja/permutation-group-ja.rd +151 -0
- data/doc-ja/polynomial-converter-ja.html +64 -0
- data/doc-ja/polynomial-converter-ja.rd +54 -0
- data/doc-ja/polynomial-ja.html +446 -0
- data/doc-ja/polynomial-ja.rd +473 -0
- data/doc-ja/residue-class-ring-ja.html +112 -0
- data/doc-ja/residue-class-ring-ja.rd +113 -0
- data/doc-ja/sample-algebraic-equation01.rb.v.rd +11 -0
- data/doc-ja/sample-algebraic-equation02.rb.v.rd +11 -0
- data/doc-ja/sample-algebraic-root01.rb.v.rd +20 -0
- data/doc-ja/sample-algebraicfield01.rb.v.rd +26 -0
- data/doc-ja/sample-algebraicfield02.rb.v.rd +15 -0
- data/doc-ja/sample-cayleyhamilton01.rb.v.rd +14 -0
- data/doc-ja/sample-diagonalization01.rb.v.rd +48 -0
- data/doc-ja/sample-divmod01.rb.v.rd +17 -0
- data/doc-ja/sample-elementary-divisor01.rb.v.rd +48 -0
- data/doc-ja/sample-factorize01.rb.v.rd +11 -0
- data/doc-ja/sample-factorize02.rb.v.rd +13 -0
- data/doc-ja/sample-factorize03.rb.v.rd +14 -0
- data/doc-ja/sample-factorize04.rb.v.rd +14 -0
- data/doc-ja/sample-factorize05.rb.v.rd +53 -0
- data/doc-ja/sample-galois-group01.rb.v.rd +27 -0
- data/doc-ja/sample-gaussian-elimination01.rb.v.rd +19 -0
- data/doc-ja/sample-geometry01.rb.v.rd +33 -0
- data/doc-ja/sample-geometry02.rb.v.rd +34 -0
- data/doc-ja/sample-geometry03.rb.v.rd +45 -0
- data/doc-ja/sample-geometry04.rb.v.rd +33 -0
- data/doc-ja/sample-geometry07.rb.v.rd +62 -0
- data/doc-ja/sample-groebner01.rb.v.rd +13 -0
- data/doc-ja/sample-groebner02.rb.v.rd +18 -0
- data/doc-ja/sample-groebner03.rb.v.rd +19 -0
- data/doc-ja/sample-group01.rb.v.rd +21 -0
- data/doc-ja/sample-jordan-form01.rb.v.rd +56 -0
- data/doc-ja/sample-jordanform01.rb.v.rd +55 -0
- data/doc-ja/sample-lagrange-multiplier01.rb.v.rd +35 -0
- data/doc-ja/sample-m-factorize01.rb.v.rd +15 -0
- data/doc-ja/sample-m-factorize02.rb.v.rd +12 -0
- data/doc-ja/sample-m-polynomial01.rb.v.rd +10 -0
- data/doc-ja/sample-map01.rb.v.rd +9 -0
- data/doc-ja/sample-polynomial01.rb.v.rd +9 -0
- data/doc-ja/sample-polynomial02.rb.v.rd +11 -0
- data/doc-ja/sample-primefield01.rb.v.rd +13 -0
- data/doc-ja/sample-quotientfield01.rb.v.rd +11 -0
- data/doc-ja/sample-quotientfield02.rb.v.rd +18 -0
- data/doc-ja/sample-quotientfield03.rb.v.rd +16 -0
- data/doc-ja/sample-quotientfield04.rb.v.rd +16 -0
- data/doc-ja/sample-set01.rb.v.rd +18 -0
- data/doc-ja/sample-splitting-field01.rb.v.rd +19 -0
- data/doc-ja/samples-ja.html +885 -0
- data/doc-ja/samples-ja.rd +221 -0
- data/doc-ja/style.css +85 -0
- data/doc-ja/todo.html +20 -0
- data/doc-ja/todo.rd +9 -0
- data/lib/algebra.rb +36 -0
- data/lib/algebra/algebraic-equation.rb +56 -0
- data/lib/algebra/algebraic-extension-field.rb +135 -0
- data/lib/algebra/algebraic-parser.rb +160 -0
- data/lib/algebra/algebraic-system.rb +224 -0
- data/lib/algebra/annihilate.rb +52 -0
- data/lib/algebra/array-supplement.rb +53 -0
- data/lib/algebra/auto-require.rb +84 -0
- data/lib/algebra/chinese-rem-th.rb +135 -0
- data/lib/algebra/combinatorial.rb +145 -0
- data/lib/algebra/elementary-divisor.rb +193 -0
- data/lib/algebra/euclidian-ring.rb +161 -0
- data/lib/algebra/factors.rb +305 -0
- data/lib/algebra/finite-group.rb +374 -0
- data/lib/algebra/finite-map.rb +201 -0
- data/lib/algebra/finite-set.rb +456 -0
- data/lib/algebra/galois-group.rb +129 -0
- data/lib/algebra/gaussian-elimination.rb +385 -0
- data/lib/algebra/groebner-basis-coeff.rb +228 -0
- data/lib/algebra/groebner-basis.rb +197 -0
- data/lib/algebra/import-module-single-thread.rb +86 -0
- data/lib/algebra/import-module.rb +491 -0
- data/lib/algebra/jordan-form.rb +114 -0
- data/lib/algebra/linear-algebra.rb +143 -0
- data/lib/algebra/localized-ring.rb +294 -0
- data/lib/algebra/m-index.rb +282 -0
- data/lib/algebra/m-polynomial-factor-int.rb +186 -0
- data/lib/algebra/m-polynomial-factor-zp.rb +114 -0
- data/lib/algebra/m-polynomial-factor.rb +315 -0
- data/lib/algebra/m-polynomial-gcd.rb +40 -0
- data/lib/algebra/m-polynomial.rb +875 -0
- data/lib/algebra/matrix-algebra-triplet.rb +292 -0
- data/lib/algebra/matrix-algebra.rb +929 -0
- data/lib/algebra/numeric-supplement.rb +123 -0
- data/lib/algebra/permutation-group.rb +257 -0
- data/lib/algebra/polynomial-converter.rb +193 -0
- data/lib/algebra/polynomial-factor-alg.rb +148 -0
- data/lib/algebra/polynomial-factor-int.rb +252 -0
- data/lib/algebra/polynomial-factor-zp.rb +165 -0
- data/lib/algebra/polynomial-factor.rb +140 -0
- data/lib/algebra/polynomial.rb +592 -0
- data/lib/algebra/powers.rb +31 -0
- data/lib/algebra/prime-gen.rb +32 -0
- data/lib/algebra/rational.rb +81 -0
- data/lib/algebra/residue-class-ring.rb +219 -0
- data/lib/algebra/sets-system.rb +43 -0
- data/lib/algebra/splitting-field.rb +103 -0
- data/lib/algebra/version.rb +3 -0
- data/sample/Makefile +10 -0
- data/sample/do-testscripts.rb +100 -0
- data/sample/sample-algebraic-equation01.rb +6 -0
- data/sample/sample-algebraic-equation02.rb +6 -0
- data/sample/sample-algebraic-root01.rb +15 -0
- data/sample/sample-algebraicfield01.rb +21 -0
- data/sample/sample-algebraicfield02.rb +10 -0
- data/sample/sample-cayleyhamilton01.rb +9 -0
- data/sample/sample-diagonalization01.rb +43 -0
- data/sample/sample-divmod01.rb +12 -0
- data/sample/sample-elementary-divisor01.rb +43 -0
- data/sample/sample-factorize01.rb +6 -0
- data/sample/sample-factorize02.rb +8 -0
- data/sample/sample-factorize03.rb +9 -0
- data/sample/sample-factorize04.rb +9 -0
- data/sample/sample-factorize05.rb +48 -0
- data/sample/sample-galois-group01.rb +22 -0
- data/sample/sample-gaussian-elimination01.rb +14 -0
- data/sample/sample-geometry01.rb +28 -0
- data/sample/sample-geometry02.rb +29 -0
- data/sample/sample-geometry03.rb +40 -0
- data/sample/sample-geometry04.rb +28 -0
- data/sample/sample-geometry07.rb +58 -0
- data/sample/sample-groebner01.rb +8 -0
- data/sample/sample-groebner02.rb +13 -0
- data/sample/sample-groebner03.rb +14 -0
- data/sample/sample-group01.rb +16 -0
- data/sample/sample-jordan-form01.rb +51 -0
- data/sample/sample-lagrange-multiplier01.rb +30 -0
- data/sample/sample-m-factorize01.rb +10 -0
- data/sample/sample-m-factorize02.rb +7 -0
- data/sample/sample-m-polynomial01.rb +5 -0
- data/sample/sample-map01.rb +4 -0
- data/sample/sample-polynomial01.rb +4 -0
- data/sample/sample-polynomial02.rb +6 -0
- data/sample/sample-primefield01.rb +8 -0
- data/sample/sample-quotientfield01.rb +6 -0
- data/sample/sample-quotientfield02.rb +13 -0
- data/sample/sample-quotientfield03.rb +11 -0
- data/sample/sample-quotientfield04.rb +11 -0
- data/sample/sample-set01.rb +13 -0
- data/sample/sample-splitting-field01.rb +14 -0
- data/sample/test-00-cayley-hamilton.rb +76 -0
- data/sample/test-00-groebner-basis.rb +274 -0
- data/sample/test-00-polynomial-factor-alg.rb +89 -0
- data/sample/test-00.list +4 -0
- data/sample/time-trial.rb +65 -0
- metadata +373 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
# Jordan Canonical Forms
|
2
|
+
#
|
3
|
+
# by Shin-ichiro Hara
|
4
|
+
#
|
5
|
+
# Version 1.00 (2001.11.01)
|
6
|
+
require 'algebra/matrix-algebra'
|
7
|
+
|
8
|
+
module Algebra
|
9
|
+
class MatrixAlgebra
|
10
|
+
def jordan_form
|
11
|
+
Algebra::JordanForm.decompose(self).first
|
12
|
+
end
|
13
|
+
|
14
|
+
def jordan_form_info
|
15
|
+
Algebra::JordanForm.decompose(self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class JordanForm
|
20
|
+
def initialize(body)
|
21
|
+
@body = body
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_matrix(ring = Integer)
|
25
|
+
mat = nil
|
26
|
+
@body.each do |x, n|
|
27
|
+
mat = if mat
|
28
|
+
mat.dsum(jordan_block_u(ring, x, n))
|
29
|
+
else
|
30
|
+
jordan_block_u(ring, x, n)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
mat
|
34
|
+
end
|
35
|
+
|
36
|
+
alias to_matrix_u to_matrix
|
37
|
+
|
38
|
+
def to_matrix_l
|
39
|
+
to_matrix_u.transpose
|
40
|
+
end
|
41
|
+
|
42
|
+
def jordan_block_u(ring, x, n)
|
43
|
+
a = Algebra.SquareMatrix(ring, n)
|
44
|
+
a.matrix do |i, j|
|
45
|
+
if i == j
|
46
|
+
x
|
47
|
+
elsif i == j - 1
|
48
|
+
ring.unity
|
49
|
+
else
|
50
|
+
ring.zero
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def jordan_block_l(ring, x, n)
|
56
|
+
jordan_block_u(ring, x, n).transpose
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.construct(elem_divs, facts, field, pfield)
|
60
|
+
a = []
|
61
|
+
elem_divs.each do |e|
|
62
|
+
facts.each do |f, n|
|
63
|
+
next if f.deg.zero? || n.zero?
|
64
|
+
f = f.convert_to(pfield)
|
65
|
+
g = e.convert_to(pfield)
|
66
|
+
|
67
|
+
raise 'insufficient decomposition' unless f.deg <= 1
|
68
|
+
k = 0
|
69
|
+
loop do
|
70
|
+
q, r = g.divmod f
|
71
|
+
break unless r.zero?
|
72
|
+
g = q
|
73
|
+
k += 1
|
74
|
+
end
|
75
|
+
a.push [-f[0], k] if k > 0
|
76
|
+
end
|
77
|
+
end
|
78
|
+
Algebra::JordanForm.new(a).to_matrix(field)
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.decompose(m)
|
82
|
+
base_ring = m.ground
|
83
|
+
base_pring = Algebra.Polynomial(base_ring, 'x')
|
84
|
+
base_alg = Algebra.SquareMatrix(base_pring, m.size)
|
85
|
+
|
86
|
+
me = m._char_matrix(base_alg).to_quint.e_diagonalize
|
87
|
+
elem_divs = me.body.diag
|
88
|
+
|
89
|
+
facts = Algebra::ElementaryDivisor.factorize(elem_divs)
|
90
|
+
dl = facts.last
|
91
|
+
field, modulus, facts, roots, elms = dl.pi.decompose(dl)
|
92
|
+
|
93
|
+
pfield = Algebra.Polynomial(field, 'x')
|
94
|
+
pfm_alg = Algebra.SquareMatrix(pfield, m.size)
|
95
|
+
|
96
|
+
jm = Algebra::JordanForm.construct(elem_divs, facts, field, pfield)
|
97
|
+
jme = jm._char_matrix(pfm_alg).to_quint.e_diagonalize
|
98
|
+
|
99
|
+
mebody = pfm_alg.convert_from(me.body)
|
100
|
+
meright = pfm_alg.convert_from(me.right)
|
101
|
+
meleft = pfm_alg.convert_from(me.left)
|
102
|
+
|
103
|
+
sR = (meright * jme.righti).i2o.evaluateR(jm)
|
104
|
+
tL = (jme.lefti * meleft).i2o.evaluateL(jm)
|
105
|
+
|
106
|
+
[jm, tL, sR, field, modulus]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
if $PROGRAM_NAME == __FILE__
|
112
|
+
j = Algebra::JordanForm.new([[2, 3], [-1, 2]])
|
113
|
+
j.to_matrix.display
|
114
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Linear Algebra
|
2
|
+
#
|
3
|
+
# by Shin-ichiro Hara
|
4
|
+
#
|
5
|
+
# Version 1.00 (2001.11.01)
|
6
|
+
|
7
|
+
require 'algebra/matrix-algebra'
|
8
|
+
require 'algebra/gaussian-elimination'
|
9
|
+
require 'algebra/polynomial'
|
10
|
+
require 'algebra/polynomial-factor'
|
11
|
+
require 'algebra/algebraic-equation'
|
12
|
+
require 'algebra/jordan-form'
|
13
|
+
|
14
|
+
module Algebra
|
15
|
+
module Orthogonalization
|
16
|
+
def orthogonalize
|
17
|
+
orth_basis = []
|
18
|
+
vectors.each_with_index do |b, i|
|
19
|
+
orth_basis.push b
|
20
|
+
next unless i > 0
|
21
|
+
orth_basis[0...i].each do |f|
|
22
|
+
orth_basis[i] -= b.inner_product(f) / f.norm2 * f
|
23
|
+
# orth_basis[i] = f.norm2*orth_basis[i] - b.inner_product(f)*f #also
|
24
|
+
end
|
25
|
+
end
|
26
|
+
self.class.collect_column { |j| orth_basis[j] }
|
27
|
+
end
|
28
|
+
|
29
|
+
def normalize
|
30
|
+
k = ground
|
31
|
+
orth_basis = []
|
32
|
+
vectors.each do |b|
|
33
|
+
k, n = Sqrt(k, b.norm2)
|
34
|
+
orth_basis.push Vector(k, size)**b / n
|
35
|
+
end
|
36
|
+
Algebra.SquareMatrix(k, size).collect_column { |j| orth_basis[j] }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class MatrixAlgebra
|
41
|
+
include Orthogonalization
|
42
|
+
# auto_req_init
|
43
|
+
# auto_req :e_diagonalize, "algebra/elementary-divisor"
|
44
|
+
# auto_req :elementary_divisor, "algebra/elementary-divisor"
|
45
|
+
require 'algebra/elementary-divisor'
|
46
|
+
end
|
47
|
+
|
48
|
+
class SquareMatrix < MatrixAlgebra
|
49
|
+
def self.symmetric(*a)
|
50
|
+
k = size * (size + 1) / 2
|
51
|
+
raise "the size of #{a.inspect} must be <= #{k}" if a.size > k
|
52
|
+
matrix do |i, j|
|
53
|
+
d = (i - j).abs
|
54
|
+
a[(i < j ? i : j) + (2 * size + 1 - d) * d / 2] || ground.zero
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
EigenSystem = Struct.new('EigenSystem',
|
59
|
+
:extfield,
|
60
|
+
:roots,
|
61
|
+
:tmatrix,
|
62
|
+
:evalues,
|
63
|
+
:addelms,
|
64
|
+
:evectors,
|
65
|
+
:espaces,
|
66
|
+
:chpoly,
|
67
|
+
:facts)
|
68
|
+
|
69
|
+
def diagonalize
|
70
|
+
chp = char_polynomial(Algebra.Polynomial(ground, 't'))
|
71
|
+
|
72
|
+
facts = chp.factorize
|
73
|
+
mdf, mods, fas, roots, proots = chp.decompose(facts)
|
74
|
+
nu = Algebra.SquareMatrix(mdf, size)
|
75
|
+
|
76
|
+
espaces = {}
|
77
|
+
evalues = []
|
78
|
+
evectors = []
|
79
|
+
roots0 = []
|
80
|
+
k = 0
|
81
|
+
facts.each do |f, _n|
|
82
|
+
dim = f.deg
|
83
|
+
if dim <= 0 # 0 might be occurred
|
84
|
+
next
|
85
|
+
elsif dim == 1
|
86
|
+
evs = [-f[0] / f[1]]
|
87
|
+
else
|
88
|
+
evs = roots[k, dim] # .reverse
|
89
|
+
roots0.push [f, evs]
|
90
|
+
end
|
91
|
+
k += dim
|
92
|
+
|
93
|
+
evs.each do |evalue|
|
94
|
+
ks = nu.const(evalue) - self
|
95
|
+
kb = ks.kernel_basis
|
96
|
+
espaces[evalue] = kb
|
97
|
+
|
98
|
+
kb.each do |v|
|
99
|
+
evalues.push evalue
|
100
|
+
evectors.push v
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
raise "can't Diagonalize" if evalues.size < size
|
106
|
+
ttype = Algebra.SquareMatrix(mdf, size)
|
107
|
+
r = ttype.collect_column { |i| evectors[i] }
|
108
|
+
# :extfield, :roots, :tmatrix, :evalues, :addelms, :evectors,
|
109
|
+
# :espaces, :chpoly, :facts
|
110
|
+
e = EigenSystem.new(mdf, roots0, r, evalues, proots, evectors,
|
111
|
+
espaces, chp, facts)
|
112
|
+
def e.to_ary
|
113
|
+
to_a
|
114
|
+
end
|
115
|
+
e
|
116
|
+
end
|
117
|
+
|
118
|
+
def solve_eigen_value_problem
|
119
|
+
puts 'A = '; display; puts
|
120
|
+
|
121
|
+
e = diagonalize
|
122
|
+
puts "Charactoristic Poly.: #{e.chpoly} => #{e.facts}"; puts
|
123
|
+
puts 'Algebraic Numbers:'
|
124
|
+
e.roots.each do |po, rs|
|
125
|
+
puts "#{rs.join(', ')} : roots of #{po} == 0"
|
126
|
+
end; puts
|
127
|
+
|
128
|
+
puts 'EigenSpaces: '
|
129
|
+
e.evalues.uniq.each do |ev|
|
130
|
+
puts "W_{#{ev}} = <#{e.espaces[ev].join(', ')}>"
|
131
|
+
end; puts
|
132
|
+
|
133
|
+
puts 'Trans. Matrix:'
|
134
|
+
puts 'P ='
|
135
|
+
e.tmatrix.display; puts
|
136
|
+
|
137
|
+
puts 'P^-1 * A * P = '; (e.tmatrix.inverse * self * e.tmatrix).display; puts
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
if __FILE__ == $PROGRAM_NAME
|
143
|
+
end
|
@@ -0,0 +1,294 @@
|
|
1
|
+
# Localization of Ring
|
2
|
+
#
|
3
|
+
# by Shin-ichiro Hara
|
4
|
+
#
|
5
|
+
# Version 1.1 (2001.04.10)
|
6
|
+
|
7
|
+
require 'algebra/euclidian-ring'
|
8
|
+
require 'algebra/algebraic-system'
|
9
|
+
|
10
|
+
module Algebra
|
11
|
+
def LocalizedRing(ring)
|
12
|
+
LocalizedRing.create(ring)
|
13
|
+
end
|
14
|
+
|
15
|
+
def RationalFunctionField(field, obj)
|
16
|
+
require 'algebra/polynomial'
|
17
|
+
k = LocalizedRing(Polynomial(field, obj))
|
18
|
+
def k.var
|
19
|
+
self[ground.var]
|
20
|
+
end
|
21
|
+
|
22
|
+
def k.to_ary
|
23
|
+
[self, var]
|
24
|
+
end
|
25
|
+
k
|
26
|
+
end
|
27
|
+
|
28
|
+
def MRationalFunctionField(field, *objs)
|
29
|
+
require 'algebra/m-polynomial'
|
30
|
+
k = LocalizedRing(MPolynomial(field, *objs))
|
31
|
+
def k.vars(*vs)
|
32
|
+
ground.vars(*vs).map { |v| self[v] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def k.to_ary
|
36
|
+
[self, *vars]
|
37
|
+
end
|
38
|
+
k.reducible = false
|
39
|
+
k
|
40
|
+
end
|
41
|
+
|
42
|
+
module_function :LocalizedRing, :RationalFunctionField, :MRationalFunctionField
|
43
|
+
|
44
|
+
class LocalizedRing
|
45
|
+
extend AlgebraCreator
|
46
|
+
include AlgebraBase
|
47
|
+
|
48
|
+
def self.create(ground)
|
49
|
+
klass = super(ground)
|
50
|
+
klass.sysvar(:reducible, true)
|
51
|
+
klass
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.reducible
|
55
|
+
@@reducible
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.reducible=(sw)
|
59
|
+
@@reducible = sw
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :numerator
|
63
|
+
attr_reader :denominator
|
64
|
+
|
65
|
+
def monomial?
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.[](num, den = nil)
|
70
|
+
den ? reduce(num, den) : unity * num
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.reduce(num, den)
|
74
|
+
reducible ? simplify(num, den) : new(num, den)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.simplify(num, den)
|
78
|
+
raise ZeroDivisionError, 'denometor is 0' if den.zero?
|
79
|
+
return zero if num.zero?
|
80
|
+
|
81
|
+
if ground.field?
|
82
|
+
num /= den
|
83
|
+
den = ground.unit
|
84
|
+
elsif ground.ufd? # ground.euclidian?
|
85
|
+
gcd = num.gcd(den)
|
86
|
+
num /= gcd
|
87
|
+
den /= gcd
|
88
|
+
# num = num.div(gcd)
|
89
|
+
# den = den.div(gcd)
|
90
|
+
end
|
91
|
+
|
92
|
+
# regulate the leading coefficient of polynomil
|
93
|
+
if defined?(Polynomial) && ground <= Polynomial
|
94
|
+
if ground.ground.field?
|
95
|
+
m = den.lc
|
96
|
+
num /= m
|
97
|
+
den /= m
|
98
|
+
elsif ground.ground.euclidian? # high cost!
|
99
|
+
m = num.cont.gcd(den.cont)
|
100
|
+
num /= m
|
101
|
+
den /= m
|
102
|
+
end
|
103
|
+
# elsif defined?(MPolynomial) && ground <= MPolynomial
|
104
|
+
end
|
105
|
+
|
106
|
+
# if den.respond_to?(:<) and den < 0
|
107
|
+
# num = -num
|
108
|
+
# den = -den
|
109
|
+
# end
|
110
|
+
new(num, den)
|
111
|
+
end
|
112
|
+
|
113
|
+
def initialize(num, den = ground.unity)
|
114
|
+
if den.respond_to?(:<=>) && den < ground.zero
|
115
|
+
num = -num
|
116
|
+
den = -den
|
117
|
+
end
|
118
|
+
@numerator = num
|
119
|
+
@denominator = den
|
120
|
+
end
|
121
|
+
|
122
|
+
def simplify
|
123
|
+
self.class.simplify(@numerator, @denominator)
|
124
|
+
end
|
125
|
+
|
126
|
+
def ==(o)
|
127
|
+
super do |o|
|
128
|
+
@numerator * o.denominator == o.numerator * @denominator
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def +(o)
|
133
|
+
super do |o|
|
134
|
+
num = @numerator * o.denominator
|
135
|
+
num_o = o.numerator * @denominator
|
136
|
+
self.class.reduce(num + num_o, @denominator * o.denominator)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def -(o)
|
141
|
+
super do |o|
|
142
|
+
num = @numerator * o.denominator
|
143
|
+
num_o = o.numerator * @denominator
|
144
|
+
self.class.reduce(num - num_o, @denominator * o.denominator)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def *(o)
|
149
|
+
super do |o|
|
150
|
+
num = @numerator * o.numerator
|
151
|
+
den = @denominator * o.denominator
|
152
|
+
self.class.reduce(num, den)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def /(o)
|
157
|
+
raise ZeroDivisionError, 'devided by 0' if o.zero?
|
158
|
+
super do |o|
|
159
|
+
num = @numerator * o.denominator
|
160
|
+
den = @denominator * o.numerator
|
161
|
+
self.class.reduce(num, den)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def unit?
|
166
|
+
!zero? # some about
|
167
|
+
end
|
168
|
+
|
169
|
+
def pdivmod(other)
|
170
|
+
[self / other, zero]
|
171
|
+
end
|
172
|
+
|
173
|
+
# def % (o)
|
174
|
+
# raise ZeroDivisionError, "devided by 0" if o.zero?
|
175
|
+
# den, a, = @denominator.gcd_coeff(o)
|
176
|
+
# num = (@numerator * a) % o
|
177
|
+
# q, r = num.divmod den
|
178
|
+
# raise "#@denominator can not divide #@numerator mod #{o}" unless r.zero?
|
179
|
+
# q
|
180
|
+
# end
|
181
|
+
|
182
|
+
def **(other)
|
183
|
+
case other
|
184
|
+
when Integer
|
185
|
+
if other > 0
|
186
|
+
num = @numerator**other
|
187
|
+
den = @denominator**other
|
188
|
+
self.class.new(num, den)
|
189
|
+
elsif other < 0
|
190
|
+
num = @denominator**-other
|
191
|
+
den = @numerator**-other
|
192
|
+
self.class.new(num, den)
|
193
|
+
elsif other.zero?
|
194
|
+
unity
|
195
|
+
end
|
196
|
+
else
|
197
|
+
x, y = other.coerce(self)
|
198
|
+
x**y
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def need_paren_in_coeff?
|
203
|
+
if @denominator.unity?
|
204
|
+
if @numerator.respond_to?(:need_paren_in_coeff?)
|
205
|
+
@numerator.need_paren_in_coeff?
|
206
|
+
elsif @numerator.is_a?(Numeric)
|
207
|
+
false
|
208
|
+
else
|
209
|
+
true
|
210
|
+
end
|
211
|
+
else
|
212
|
+
false
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def to_s
|
217
|
+
n = if @numerator.respond_to?(:need_paren_in_coeff?) &&
|
218
|
+
@numerator.need_paren_in_coeff? &&
|
219
|
+
!@denominator.unity?
|
220
|
+
"(#{@numerator})"
|
221
|
+
else
|
222
|
+
@numerator.to_s
|
223
|
+
end
|
224
|
+
d = if @denominator.respond_to?(:need_paren_in_coeff?) &&
|
225
|
+
@denominator.need_paren_in_coeff? &&
|
226
|
+
!@denominator.is_a?(Integer)
|
227
|
+
"(#{@denominator})"
|
228
|
+
else
|
229
|
+
@denominator.to_s
|
230
|
+
end
|
231
|
+
if @denominator.unity?
|
232
|
+
n.to_s
|
233
|
+
else
|
234
|
+
n + '/' + d
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def inspect
|
239
|
+
to_s
|
240
|
+
# sprintf("%s(%s/%s)", self.class, @numerator.inspect, @denominator.inspect)
|
241
|
+
end
|
242
|
+
|
243
|
+
def hash
|
244
|
+
raise 'hash is undefined'
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
if __FILE__ == $PROGRAM_NAME
|
250
|
+
require 'algebra/polynomial'
|
251
|
+
require 'algebra/rational'
|
252
|
+
require 'algebra/residue-class-ring'
|
253
|
+
include Algebra
|
254
|
+
|
255
|
+
Q = LocalizedRing(Integer)
|
256
|
+
a = Q.new(3, 5)
|
257
|
+
b = Q.new(5, 3)
|
258
|
+
p [a + b, a - b, a * b, a / b, a + 3, 1 + a]
|
259
|
+
|
260
|
+
Z13 = ResidueClassRing(Integer, 13)
|
261
|
+
|
262
|
+
Z13x = Polynomial(Z13, 'x')
|
263
|
+
x = Z13x.var
|
264
|
+
QZ13x = LocalizedRing(Z13x)
|
265
|
+
a = QZ13x[x**2 + x + 1, x**2 - 1]
|
266
|
+
b = QZ13x[x + 1, x**2 + 3 * x + 2]
|
267
|
+
p a + b
|
268
|
+
p((a + b)**4)
|
269
|
+
puts
|
270
|
+
|
271
|
+
Rx = Polynomial(Rational, 'x')
|
272
|
+
# Rx = Polynomial(Z13, "x")
|
273
|
+
x = Rx.var
|
274
|
+
QRx = LocalizedRing(Rx)
|
275
|
+
x = QRx[x]
|
276
|
+
a = (x**2 + 1) / (x**3 + x + 1)
|
277
|
+
QRxy = Polynomial(QRx, 'y')
|
278
|
+
y = QRxy.var
|
279
|
+
AFF = ResidueClassRing(QRxy, y**3 + a * y + 1)
|
280
|
+
y = AFF[y]
|
281
|
+
p((y + x)**3)
|
282
|
+
|
283
|
+
F = RationalFunctionField(Rational, 'x')
|
284
|
+
x = F.var
|
285
|
+
p ( 1 / (x**2 - 1) - 1 / (x**3 - 1))
|
286
|
+
|
287
|
+
require 'algebra/mathn'
|
288
|
+
require 'algebra/algebraic-extension-field'
|
289
|
+
S = AlgebraicExtensionField(Rational, 'a') { |a| a**2 - 2 }
|
290
|
+
QSx = RationalFunctionField(S, 'x')
|
291
|
+
x = QSx.var
|
292
|
+
a = S.var
|
293
|
+
p((a / 4 * x + 1 / 2) / (x**2 + a * x + 1) + (-a / 4 * x + 1 / 2) / (x**2 - a * x + 1))
|
294
|
+
end
|