Attachment 'S_units_for_etale_algebras.patch'
Download 1 # HG changeset patch
2 # User Robert L. Miller <[email protected]>
3 # Date 1259959420 18000
4 # Node ID 78cb8fa60207972fc9faccbe0a83af0cd30bac14
5 # Parent 51902c8b223bc37104c31683d0456b03c13dc06d
6 Implement S-class groups and S-units for polynomial rings over a number field.
7
8 diff -r 51902c8b223b -r 78cb8fa60207 sage/rings/number_field/number_field_ideal.py
9 --- a/sage/rings/number_field/number_field_ideal.py Thu Dec 03 14:02:18 2009 -0500
10 +++ b/sage/rings/number_field/number_field_ideal.py Fri Dec 04 15:43:40 2009 -0500
11 @@ -88,6 +88,60 @@
12 """
13 return field.pari_nf().getattr('zk') * hnf
14
15 +def convert_from_idealprimedec_form(field, ideal):
16 + """
17 + INPUT:
18 +
19 + - ``field`` - a number field
20 +
21 + - ``ideal`` - a pari ideal, as output by the idealprimedec function
22 +
23 + EXAMPLE::
24 +
25 + sage: from sage.rings.number_field.number_field_ideal import convert_from_idealprimedec_form
26 + sage: K.<a> = NumberField(x^2 + 3)
27 + sage: K_bnf = gp(K.pari_bnf())
28 + sage: ideal = K_bnf.idealprimedec(3)[1]
29 + sage: convert_from_idealprimedec_form(K, ideal)
30 + Fractional ideal (1/2*a - 3/2)
31 + sage: K.factor(3)
32 + (Fractional ideal (1/2*a - 3/2))^2
33 +
34 + """
35 + p = ZZ(ideal[1])
36 + alpha = field( field.pari_nf().getattr('zk') * ideal[2] )
37 + return field.ideal(p, alpha)
38 +
39 +def convert_to_idealprimedec_form(field, ideal):
40 + """
41 + INPUT:
42 +
43 + - ``field`` - a number field
44 +
45 + - ``ideal`` - a prime ideal
46 +
47 + NOTE:
48 +
49 + The algorithm implemented right now is *immensely* stupid, but works. It
50 + should eventually be replaced with something better.
51 +
52 + EXAMPLE::
53 +
54 + sage: from sage.rings.number_field.number_field_ideal import convert_to_idealprimedec_form
55 + sage: K.<a> = NumberField(x^2 + 3)
56 + sage: P = K.ideal(a/2-3/2)
57 + sage: convert_to_idealprimedec_form(K, P)
58 + [3, [1, 2]~, 2, 1, [1, -1]~]
59 +
60 + """
61 + p = ideal.residue_field().characteristic()
62 + from sage.interfaces.gp import gp
63 + K_bnf = gp(field.pari_bnf())
64 + for primedecform in K_bnf.idealprimedec(p):
65 + if convert_from_idealprimedec_form(field, primedecform) == ideal:
66 + return primedecform
67 + raise RuntimeError
68 +
69 class NumberFieldIdeal(Ideal_generic):
70 """
71 An ideal of a number field.
72 diff -r 51902c8b223b -r 78cb8fa60207 sage/rings/polynomial/polynomial_quotient_ring.py
73 --- a/sage/rings/polynomial/polynomial_quotient_ring.py Thu Dec 03 14:02:18 2009 -0500
74 +++ b/sage/rings/polynomial/polynomial_quotient_ring.py Fri Dec 04 15:43:40 2009 -0500
75 @@ -570,6 +570,163 @@
76 return self(self.polynomial_ring().random_element(degree=self.degree()-1))
77
78
79 + def S_class_group(self, S, proof=True):
80 + """
81 + If this quotient ring is over a number field K, by a polynomial with
82 + nonzero discriminant, and S is a set of primes of K, this function
83 + returns the S-class group.
84 + """
85 + return self._S_class_group_and_units(S, proof=proof)[1]
86 +
87 + def class_group(self, proof=True):
88 + """
89 + If this quotient ring is over a number field K, by a polynomial of
90 + nonzero discriminant, returns the class group.
91 + """
92 + return self._S_class_group_and_units([], proof=proof)[1]
93 +
94 + def S_units(self, S, proof=True):
95 + """
96 + If this quotient ring is over a number field K, by a polynomial with
97 + nonzero discriminant, and S is a set of primes of K, this function
98 + returns the S-units.
99 + """
100 + return self._S_class_group_and_units(S, proof=proof)[0]
101 +
102 + def units(self, proof=True):
103 + """
104 + If this quotient ring is over a number field K, by a polynomial of
105 + nonzero discriminant, returns the units.
106 + """
107 + return self._S_class_group_and_units([], proof=proof)[0]
108 +
109 + def _S_class_group_and_units(self, S, proof=True):
110 + from sage.rings.number_field.all import is_NumberField
111 + K = self.base_ring()
112 + if not is_NumberField(K) or not self.__polynomial.is_squarefree():
113 + raise NotImplementedError
114 +
115 + from sage.rings.ideal import is_Ideal
116 + for p in S:
117 +# try:
118 + assert is_Ideal(p)
119 + assert p.ring() is K or p.ring() is K.ring_of_integers() # second check due to inconsistency over QQ - see # 7596
120 + assert p.is_prime()
121 +# except AssertionError:
122 +# raise TypeError("S must be a list of prime ideals of the base field.")
123 +
124 + from sage.rings.number_field.number_field import NumberField
125 + from sage.rings.number_field.number_field_ideal import \
126 + convert_to_idealprimedec_form, convert_from_idealprimedec_form
127 + from sage.interfaces.gp import gp
128 +
129 + F = self.__polynomial.factor()
130 + rel_fields = []
131 + abs_fields = []
132 + isos = []
133 + iso_classes = []
134 + i = 0
135 + for f, _ in F:
136 + D = K.extension(f, 'x'+str(i))
137 + rel_fields.append(D)
138 + D_abs = D.absolute_field('y'+str(i))
139 + abs_fields.append(D_abs)
140 + i += 1
141 +
142 + seen_before = False
143 + j = 0
144 + for D_iso,_ in iso_classes:
145 + if D_abs.is_isomorphic(D_iso):
146 + seen_before = True; break
147 + j += 1
148 + if seen_before:
149 + isos.append((D_iso.embeddings(D_abs)[0], j))
150 + else:
151 + S_abs = []
152 + for p in S:
153 + abs_gens = []
154 + for g in D.ideal([a for a in p.gens()]).gens(): # this line looks a bit silly, due to inconsistency over QQ - see # 7596
155 + abs_gens.append(D_abs.structure()[1](g))
156 + S_abs += [pp for pp,_ in D_abs.ideal(abs_gens).factor()]
157 + iso_classes.append((D_abs,S_abs))
158 + isos.append((D_abs.embeddings(D_abs)[0], j))
159 +
160 + from sage.rings.all import QQ, ZZ
161 + component_S_units = []
162 + component_S_class_groups = []
163 + component_S_class_str = []
164 + for D_iso, S_iso in iso_classes:
165 + deg = D_iso.degree()
166 + D_gp = gp(D_iso.pari_bnf())
167 + if proof:
168 + assert D_gp.bnfcertify() == 1
169 + # if the result is not provable, may output an
170 + # error message, or loop indefinitely
171 +
172 + S_gp = [convert_to_idealprimedec_form(D_iso, p) for p in S_iso]
173 + units = []
174 +
175 + result = D_gp.bnfsunit(S_gp)
176 + x = D_iso.gen()
177 + for unit in result[1]:
178 + sage_unit = 0
179 + for i in xrange(unit.poldegree()+1):
180 + sage_unit += QQ(unit.polcoeff(i))*x**i
181 + units.append(sage_unit)
182 + units += D_iso.unit_group().gens()
183 + component_S_units.append(units)
184 +
185 + IB = []
186 + for f_gp in D_gp[7][7]:
187 + f = 0
188 + for i in xrange(f_gp.length()):
189 + f += QQ(f_gp.polcoeff(i))*x**i
190 + IB.append(f)
191 + clgp_gens = []
192 + for M in result[5][3]:
193 + ideal_gens = []
194 + for i in xrange(1, deg+1):
195 + col = []
196 + for j in xrange(1, deg+1):
197 + col.append(ZZ(M[j,i]))
198 + ideal_gens.append(sum([IB[j]*col[j] for j in xrange(deg)]))
199 + clgp_gens.append(D_iso.ideal(ideal_gens))
200 + component_S_class_groups.append(clgp_gens)
201 +
202 + from sage.rings.arith import crt
203 + units = []
204 + clgp_gens = []
205 + moduli = [D.relative_polynomial() for D in rel_fields]
206 + for i in xrange(len(rel_fields)):
207 + phi = isos[i][0]
208 + back_to_rel = phi.codomain().structure()[0]
209 + for unit in component_S_units[isos[i][1]]:
210 + rel_unit = back_to_rel(phi(unit))
211 + prod_unit = []
212 + for j in xrange(i):
213 + prod_unit.append(rel_fields[j](1))
214 + prod_unit.append(back_to_rel(phi(unit)))
215 + for j in xrange(len(rel_fields) - i - 1):
216 + prod_unit.append(rel_fields[j](1))
217 + poly_unit = crt([u_i.polynomial() for u_i in prod_unit], moduli, None, None)
218 + units.append(self(poly_unit))
219 + for clgp_gen in component_S_class_groups[isos[i][1]]:
220 + poly_ideal_gens = []
221 + for ideal_gen in clgp_gen.gens():
222 + rel_ideal_gen = back_to_rel(phi(ideal_gen))
223 + prod_ideal_gen = []
224 + for j in xrange(i):
225 + prod_ideal_gen.append(rel_fields[j](1))
226 + prod_ideal_gen.append(back_to_rel(phi(ideal_gen)))
227 + for j in xrange(len(rel_fields) - i - 1):
228 + prod_ideal_gen.append(rel_fields[j](1))
229 + poly_ideal_gen = crt([u_i.polynomial() for u_i in prod_ideal_gen], moduli, None, None)
230 + poly_ideal_gens.append(poly_ideal_gen)
231 + clgp_gens.append(self.ideal(poly_ideal_gens))
232 +
233 +
234 + return units, clgp_gens
235 +
236 class PolynomialQuotientRing_domain(PolynomialQuotientRing_generic, sage.rings.integral_domain.IntegralDomain):
237 """
238 EXAMPLES::
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.