/
MPolyRing.jl
183 lines (148 loc) · 5.08 KB
/
MPolyRing.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# Since coeff_map is at the third position, we wannot use a variable
# with default argument
################################################################################
#
# Domains of type MPolyRing
#
################################################################################
################################################################################
#
# Constructos
#
################################################################################
function _check_imgs(S::NCRing, imgs)
n = length(imgs)
for i in 2:n, j in 1:(i - 1)
@req imgs[i] * imgs[j] == imgs[j] * imgs[i] "Images $i and $j do not commute"
end
return nothing
end
# no check for commutative codomains
_check_imgs(S::Ring, imgs) = nothing
@doc raw"""
hom(R::MPolyRing, S::NCRing, coeff_map, images::Vector; check::Bool = true)
hom(R::MPolyRing, S::NCRing, images::Vector; check::Bool = true)
Given a homomorphism `coeff_map` from `C` to `S`, where `C` is the
coefficient ring of `R`, and given a vector `images` of `nvars(R)`
elements of `S`, return the homomorphism `R` $\to$ `S` whose restriction
to `C` is `coeff_map`, and which sends the `i`-th variable of `R` to the
`i`-th entry of `images`.
If no coefficient map is entered, invoke a canonical homomorphism of `C`
to `S`, if such a homomorphism exists, and throw an error, otherwise.
!!! note
In case `check = true` (default), the function checks the conditions below:
- If `S` is graded, the assigned images must be homogeneous with respect to the given grading.
- If `S` is noncommutative, the assigned images must pairwise commute.
# Examples
```jldoctest
julia> K, a = finite_field(2, 2, "a");
julia> R, (x, y) = polynomial_ring(K, ["x", "y"]);
julia> F = hom(R, R, z -> z^2, [y, x])
Ring homomorphism
from multivariate polynomial ring in 2 variables over GF(2, 2)
to multivariate polynomial ring in 2 variables over GF(2, 2)
defined by
x -> y
y -> x
with map on coefficients
#1
julia> F(a * y)
(a + 1)*x
julia> Qi, i = quadratic_field(-1)
(Imaginary quadratic field defined by x^2 + 1, sqrt(-1))
julia> S, (x, y) = polynomial_ring(Qi, ["x", "y"]);
julia> G = hom(S, S, hom(Qi, Qi, -i), [x^2, y^2])
Ring homomorphism
from multivariate polynomial ring in 2 variables over Qi
to multivariate polynomial ring in 2 variables over Qi
defined by
x -> x^2
y -> y^2
with map on coefficients
Map: Qi -> Qi
julia> G(x+i*y)
x^2 - sqrt(-1)*y^2
julia> R, (x, y) = polynomial_ring(ZZ, ["x", "y"]);
julia> f = 3*x^2+2*x+1;
julia> S, (x, y) = polynomial_ring(GF(2), ["x", "y"]);
julia> H = hom(R, S, gens(S))
Ring homomorphism
from multivariate polynomial ring in 2 variables over ZZ
to multivariate polynomial ring in 2 variables over GF(2)
defined by
x -> x
y -> y
julia> H(f)
x^2 + 1
```
"""
function hom(R::MPolyRing, S::NCRing, coeff_map, images::Vector; check::Bool = true)
n = ngens(R)
@req n == length(images) "Number of images must be $n"
# Now coerce into S or throw an error if not possible
imgs = _coerce(S, images)
@check begin
_check_imgs(S, imgs)
_check_homo(S, imgs) # defined in MPolyAnyMap.jl
end
return MPolyAnyMap(R, S, coeff_map, copy(imgs)) # copy because of #655
end
function hom(R::MPolyRing, S::NCRing, images::Vector; check::Bool = true)
n = ngens(R)
@req n == length(images) "Number of images must be $n"
# Now coerce into S or throw an error if not possible
imgs = _coerce(S, images)
@check begin
_check_imgs(S, imgs)
_check_homo(S, imgs) # defined in MPolyAnyMap.jl
end
return MPolyAnyMap(R, S, nothing, copy(imgs)) # copy because of #655
end
################################################################################
#
# Evaluation functions
#
################################################################################
function _evaluate_plain(F::MPolyAnyMap{<: MPolyRing}, u)
return evaluate(u, F.img_gens)
end
# See the comment in MPolyQuo.jl
function _evaluate_plain(F::MPolyAnyMap{<:MPolyRing, <:MPolyQuoRing}, u)
A = codomain(F)
v = evaluate(lift(u), lift.(_images(F)))
return simplify(A(v))
end
function _evaluate_general(F::MPolyAnyMap{<: MPolyRing}, u)
if domain(F) === codomain(F) && coefficient_map(F) === nothing
return evaluate(map_coefficients(coefficient_map(F), u,
parent = domain(F)), F.img_gens)
else
S = temp_ring(F)
if S !== nothing
return evaluate(map_coefficients(coefficient_map(F), u,
parent = S), F.img_gens)
else
return evaluate(map_coefficients(coefficient_map(F), u), F.img_gens)
end
end
end
# one more intermediate function
function _evaluate_help(F::MPolyAnyMap{<: MPolyRing, <: Any, Nothing}, g)
return _evaluate_plain(F, g)
end
function _evaluate_help(F::MPolyAnyMap{<: MPolyRing}, g)
return _evaluate_general(F, g)
end
function (F::MPolyAnyMap{<: MPolyRing})(g)
if g isa elem_type(domain(F))
if coefficient_map(F) === nothing
return _evaluate_plain(F, g)
else
return _evaluate_general(F, g)
end
else
gg = domain(F)(g)
@assert parent(gg) === domain(F)
return F(gg)
end
end