1 | /////////////////////////////////////////////////////////////////////////////// |
---|
2 | version="version moddiq.lib 4.1.2.0 Feb_2020 "; // $Id$ |
---|
3 | category="Commutative Algebra"; |
---|
4 | info=" |
---|
5 | LIBRARY: moddiq.lib Double ideal quotient using modular methods |
---|
6 | |
---|
7 | AUTHORS: Y. Ishihara yishihara@rikkyo.ac.jp |
---|
8 | |
---|
9 | OVERVIEW: |
---|
10 | A library for computing ideal quotient and saturation in the polynomial ring |
---|
11 | over the rational numbers using modular methods. |
---|
12 | |
---|
13 | REFERENCES: |
---|
14 | M. Noro, K. Yokoyama: Usage of Modular Techniques for Efficient Computation of Ideal Operations. |
---|
15 | Math.Comput.Sci. 12: 1, 1-32. (2017). |
---|
16 | |
---|
17 | PROCEDURES: |
---|
18 | modQuotient(I,J); standard basis of (I:J) using modular methods |
---|
19 | modSat(I,J); standard basis of (I:J^\infty) using modular methods |
---|
20 | "; |
---|
21 | //UPCOMING PROCEDURES: |
---|
22 | // moddiq(I,J); standard basis of (I:(I:J)) using modular methods |
---|
23 | // modAssCheck(I,P); check if P is associated of I or not using modular methods |
---|
24 | // IntermediatePrimaryDecomposition(I); compute intermediate primary decomposition of I |
---|
25 | // by using modular method |
---|
26 | |
---|
27 | LIB "poly.lib"; |
---|
28 | LIB "elim.lib"; |
---|
29 | LIB "modular.lib"; |
---|
30 | LIB "modstd.lib"; |
---|
31 | |
---|
32 | proc modQuotient(def I, def J) |
---|
33 | "USAGE: modQuotient(I,J); I,J ideal |
---|
34 | RETURN: a standard basis of (I:J) |
---|
35 | NOTE: The procedure computes a standard basis of (I:J) (over the rational |
---|
36 | numbers) by using modular methods. |
---|
37 | SEE ALSO: modular; quotient |
---|
38 | EXAMPLE: example modQuotient; shows an example" |
---|
39 | { |
---|
40 | I = modStd(I); |
---|
41 | def IJ=modular("quotient",list(I,J),primeTest_quotient, |
---|
42 | Modstd::deleteUnluckyPrimes_std,pTest_quotient,finalTest_quotient); |
---|
43 | return(IJ); |
---|
44 | } |
---|
45 | example |
---|
46 | { |
---|
47 | "EXAMPLE:"; |
---|
48 | echo=2; |
---|
49 | ring r=0,x(1..6),dp; |
---|
50 | ideal i=cyclic(6); |
---|
51 | ideal j=-15*var(5)+16*var(6)^3-60*var(6)^2+225*var(6)-4,2*var(5)^2-7*var(5)+2*var(6)^2-7*var(6)+28,(4*var(6)-1)*var(5)-var(6)+4,4*var(1)+var(5)+var(6),4*var(2)+var(5)+var(6),4*var(3)+var(5)+var(6),4*var(4)+var(5)+var(6); |
---|
52 | modQuotient(i,modQuotient(i,j)); |
---|
53 | ideal id2=x(1)^2+x(1)*x(2)*x(3),x(2)^2-x(3)^3*x(2),x(3)^3+x(2)^5*x(1)*x(3); |
---|
54 | quotient(id2,maxideal(3)); |
---|
55 | } |
---|
56 | |
---|
57 | /* test if a prime number p is permissible for an ideal I |
---|
58 | * i.e. it does not divide the denominator of any of the coeffients |
---|
59 | * or numerator of any of the leading coefficients */ |
---|
60 | static proc isPermissible(int p,ideal I) |
---|
61 | { |
---|
62 | /* erase zero generators */ |
---|
63 | def J = simplify(I, 2); |
---|
64 | |
---|
65 | /* clear denominators and compute the leading coeffients of |
---|
66 | the cleared one and the original one*/ |
---|
67 | int n = ncols(J); |
---|
68 | int i; |
---|
69 | ideal K; |
---|
70 | for(i = n; i > 0; i--) |
---|
71 | { |
---|
72 | K[i] = leadcoef(cleardenom(J[i]))*var(1)+leadcoef(J[i]); |
---|
73 | } |
---|
74 | |
---|
75 | /* change to characteristic p */ |
---|
76 | def br = basering; |
---|
77 | list lbr = ringlist(br); |
---|
78 | if (typeof(lbr[1]) == "int") { lbr[1] = p; } |
---|
79 | else { lbr[1][1] = p; } |
---|
80 | def rp = ring(lbr); |
---|
81 | setring(rp); |
---|
82 | ideal Kp = fetch(br, K); |
---|
83 | |
---|
84 | /* test if any leading coefficient is missing */ |
---|
85 | if (intvec(size(Kp[1..n])) != 2:n) { setring(br); return(0); } |
---|
86 | setring(br); |
---|
87 | return(1); |
---|
88 | } |
---|
89 | |
---|
90 | /* test if the prime p is permissible for I and J */ |
---|
91 | static proc primeTest_quotient(int p, alias list args) |
---|
92 | { |
---|
93 | def I = args[1]; |
---|
94 | def J = args[2]; |
---|
95 | if(!isPermissible(p,I)){print("not permissible");return(0);} |
---|
96 | if(!isPermissible(p,J)){print("not permissible");return(0);} |
---|
97 | return(1); |
---|
98 | } |
---|
99 | |
---|
100 | /* test if 'command' applied to 'args' in characteristic p is the same as |
---|
101 | 'result' mapped to characteristic p */ |
---|
102 | static proc pTest_quotient(string command, alias list args, alias def result, |
---|
103 | int p) |
---|
104 | { |
---|
105 | /* change to characteristic p */ |
---|
106 | def br = basering; |
---|
107 | list lbr = ringlist(br); |
---|
108 | if (typeof(lbr[1]) == "int") { lbr[1] = p; } |
---|
109 | else { lbr[1][1] = p; } |
---|
110 | def rp = ring(lbr); |
---|
111 | setring(rp); |
---|
112 | list args_fetched = fetch(br, args); |
---|
113 | def Ip = args_fetched[1]; |
---|
114 | def Jp = args_fetched[2]; |
---|
115 | def Gp = fetch(br, result); |
---|
116 | def IJp; |
---|
117 | attrib(Ip, "isSB", 1); |
---|
118 | attrib(Gp, "isSB", 1); |
---|
119 | |
---|
120 | /* test if (Ip:Jp) is in Gp */ |
---|
121 | /* compute command(args) */ |
---|
122 | execute("IJp = "+command+"(Ip,Jp);"); |
---|
123 | int i; |
---|
124 | for (i = ncols(IJp); i > 0; i--) |
---|
125 | { |
---|
126 | if (reduce(IJp[i], Gp, 1) != 0) |
---|
127 | { |
---|
128 | setring(br); |
---|
129 | return(0); |
---|
130 | } |
---|
131 | } |
---|
132 | |
---|
133 | /* test if Gp is in (Ip:Jp) */ |
---|
134 | ideal GpJp=Gp*Jp; |
---|
135 | for (i = ncols(GpJp); i > 0; i--) |
---|
136 | { |
---|
137 | if (reduce(GpJp[i], Ip, 1) != 0) { setring(br); return(0); } |
---|
138 | } |
---|
139 | setring(br); |
---|
140 | return(1); |
---|
141 | } |
---|
142 | |
---|
143 | /* test if 'result' is a GB of (I:J) */ |
---|
144 | static proc finalTest_quotient(string command, alias list args, def result) |
---|
145 | { |
---|
146 | /* test if result is in (I:J)*/ |
---|
147 | attrib(result, "isSB", 1); |
---|
148 | int i; |
---|
149 | def IJ=result*args[2]; |
---|
150 | for (i = ncols(IJ); i > 0; i--) |
---|
151 | { |
---|
152 | if (reduce(IJ[i], args[1], 1) != 0) {print("fail") return(0); } |
---|
153 | } |
---|
154 | return(1); |
---|
155 | } |
---|
156 | |
---|
157 | proc modSat(def I, def J) |
---|
158 | "USAGE: modSat(I,J); I,J ideal |
---|
159 | RETURN: a standard basis of (I:J^\infty) |
---|
160 | NOTE: The procedure computes a standard basis of (I:J^\infty) (over the rational |
---|
161 | numbers) by using modular methods. |
---|
162 | KEYWORDS: saturation |
---|
163 | SEE ALSO: modular; sat |
---|
164 | EXAMPLE: example modSat; shows an example" |
---|
165 | { |
---|
166 | I = modStd(I); |
---|
167 | def IJ=modular("sat",list(I,J),primeTest_sat, |
---|
168 | deleteUnluckyPrimes_sat,pTest_sat,finalTest_sat); |
---|
169 | return(IJ); |
---|
170 | } |
---|
171 | example |
---|
172 | { |
---|
173 | "EXAMPLE:"; |
---|
174 | echo=2; |
---|
175 | ring r=0,x(1..6),dp; |
---|
176 | ideal i=cyclic(6); |
---|
177 | ideal j=-15*var(5)+16*var(6)^3-60*var(6)^2+225*var(6)-4,2*var(5)^2-7*var(5)+2*var(6)^2-7*var(6)+28,(4*var(6)-1)*var(5)-var(6)+4,4*var(1)+var(5)+var(6),4*var(2)+var(5)+var(6),4*var(3)+var(5)+var(6),4*var(4)+var(5)+var(6); |
---|
178 | modSat(i,modSat(i,j)[1])[1]; |
---|
179 | poly F = x(1)^5+x(2)^5+(x(1)-x(2))^2*x(1)*x(2)*x(3); |
---|
180 | ideal J = jacob(F); |
---|
181 | modSat(J,maxideal(1)); |
---|
182 | } |
---|
183 | |
---|
184 | /* test if the prime p is permissible for I and J */ |
---|
185 | static proc primeTest_sat(int p, alias list args) |
---|
186 | { |
---|
187 | return(primeTest_quotient(p,args)); |
---|
188 | } |
---|
189 | |
---|
190 | /* find entries in modresults which come from unlucky primes. |
---|
191 | * For this, sort the entries into categories depending on their leading |
---|
192 | * ideal and return the indices in all but the biggest category. |
---|
193 | * Referring to Modstd::deleteUnlickyPrimes_std. */ |
---|
194 | static proc deleteUnluckyPrimes_sat(alias list modresults) |
---|
195 | { |
---|
196 | int size_modresults = size(modresults); |
---|
197 | |
---|
198 | /* sort results into categories. |
---|
199 | * each category is represented by three entries: |
---|
200 | * - the corresponding leading ideal |
---|
201 | * - the number of elements |
---|
202 | * - the indices of the elements |
---|
203 | */ |
---|
204 | list cat; |
---|
205 | int size_cat; |
---|
206 | def L=modresults[1][1]; // dummy assign to get the type of L |
---|
207 | int i; |
---|
208 | int j; |
---|
209 | for (i = 1; i <= size_modresults; i++) |
---|
210 | { |
---|
211 | L = lead(modresults[i][1]); |
---|
212 | attrib(L, "isSB", 1); |
---|
213 | for (j = 1; j <= size_cat; j++) |
---|
214 | { |
---|
215 | if (size(L) == size(cat[j][1])) |
---|
216 | { |
---|
217 | if (size(reduce(L, cat[j][1], 5)) == 0) |
---|
218 | { |
---|
219 | if (size(reduce(cat[j][1], L, 5)) == 0) |
---|
220 | { |
---|
221 | cat[j][2] = cat[j][2]+1; |
---|
222 | cat[j][3][cat[j][2]] = i; |
---|
223 | break; |
---|
224 | } |
---|
225 | } |
---|
226 | } |
---|
227 | } |
---|
228 | if (j > size_cat) |
---|
229 | { |
---|
230 | size_cat++; |
---|
231 | cat[size_cat] = list(); |
---|
232 | cat[size_cat][1] = L; |
---|
233 | cat[size_cat][2] = 1; |
---|
234 | cat[size_cat][3] = list(i); |
---|
235 | } |
---|
236 | } |
---|
237 | |
---|
238 | /* find the biggest categories */ |
---|
239 | int cat_max = 1; |
---|
240 | int max = cat[1][2]; |
---|
241 | for (i = 2; i <= size_cat; i++) |
---|
242 | { |
---|
243 | if (cat[i][2] > max) |
---|
244 | { |
---|
245 | cat_max = i; |
---|
246 | max = cat[i][2]; |
---|
247 | } |
---|
248 | } |
---|
249 | |
---|
250 | /* return all other indices */ |
---|
251 | list unluckyIndices; |
---|
252 | for (i = 1; i <= size_cat; i++) |
---|
253 | { |
---|
254 | if (i != cat_max) { unluckyIndices = unluckyIndices + cat[i][3]; } |
---|
255 | } |
---|
256 | return(unluckyIndices); |
---|
257 | } |
---|
258 | |
---|
259 | /* test if 'command' applied to 'args' in characteristic p is the same as |
---|
260 | 'result' mapped to characteristic p */ |
---|
261 | static proc pTest_sat(string command, alias list args, alias def result, |
---|
262 | int p) |
---|
263 | { |
---|
264 | /* change to characteristic p */ |
---|
265 | def br = basering; |
---|
266 | list lbr = ringlist(br); |
---|
267 | if (typeof(lbr[1]) == "int") { lbr[1] = p; } |
---|
268 | else { lbr[1][1] = p; } |
---|
269 | def rp = ring(lbr); |
---|
270 | setring(rp); |
---|
271 | list args_fetched = fetch(br, args); |
---|
272 | def Ip = args_fetched[1]; |
---|
273 | def Jp = args_fetched[2]; |
---|
274 | def pResult = fetch(br, result); |
---|
275 | def Gp=pResult[1]; |
---|
276 | def IJp; |
---|
277 | attrib(Ip, "isSB", 1); |
---|
278 | attrib(Gp, "isSB", 1); |
---|
279 | |
---|
280 | /* test if (Ip:Jp^\infty) is in Gp */ |
---|
281 | /* compute command(args) */ |
---|
282 | execute("IJp = "+command+"(Ip,Jp)[1];"); |
---|
283 | int i; |
---|
284 | for (i = ncols(IJp); i > 0; i--) |
---|
285 | { |
---|
286 | if (reduce(IJp[i], Gp, 1) != 0) |
---|
287 | { |
---|
288 | setring(br); |
---|
289 | return(0); |
---|
290 | } |
---|
291 | } |
---|
292 | |
---|
293 | /* test if Gp is in (Ip:Jp^\infty) */ |
---|
294 | for (i = ncols(Gp); i > 0; i--) |
---|
295 | { |
---|
296 | if (reduce(Gp[i], IJp, 1) != 0) { setring(br); return(0); } |
---|
297 | } |
---|
298 | setring(br); |
---|
299 | return(1); |
---|
300 | } |
---|
301 | |
---|
302 | /* test if 'result' is a GB of (I:J^\infty) */ |
---|
303 | static proc finalTest_sat(string command, alias list args, def result) |
---|
304 | { |
---|
305 | /* test if result is in (I:J^\infty)*/ |
---|
306 | int i; |
---|
307 | ideal H = result[1]; |
---|
308 | int m=0; |
---|
309 | for (i = 0 ; i < result[2]; i++){m++;} |
---|
310 | ideal JGm; |
---|
311 | for (i = 0 ; i < size(args[2]); i++) |
---|
312 | { |
---|
313 | JGm = JGm + args[2]^m; |
---|
314 | } |
---|
315 | def K=H*JGm; |
---|
316 | for (i = ncols(K); i > 0; i--) |
---|
317 | { |
---|
318 | if (reduce(K[i], args[1], 1) != 0) {print("fail") return(0); } |
---|
319 | } |
---|
320 | return(1); |
---|
321 | } |
---|
322 | |
---|
323 | |
---|