1 | //syntax of nselect adopted (intvec instead of two integers), |
---|
2 | //help for finitenessTest and mapIsFinite edited |
---|
3 | //new proc nonZeroEntry(id), used to fix a bug in proc finitenessTest |
---|
4 | /////////////////////////////////////////////////////////////////////////////// |
---|
5 | version="$Id: algebra.lib,v 1.19 2009-02-20 09:26:50 Singular Exp $"; |
---|
6 | category="Commutative Algebra"; |
---|
7 | info=" |
---|
8 | LIBRARY: algebra.lib Compute with Algbras and Algebra Maps |
---|
9 | AUTHORS: Gert-Martin Greuel, greuel@mathematik.uni-kl.de, |
---|
10 | @* Agnes Eileen Heydtmann, agnes@math.uni-sb.de, |
---|
11 | @* Gerhard Pfister, pfister@mathematik.uni-kl.de |
---|
12 | |
---|
13 | PROCEDURES: |
---|
14 | algebra_containment(); query of algebra containment |
---|
15 | module_containment(); query of module containment over a subalgebra |
---|
16 | inSubring(p,I); test whether poly p is in subring generated by I |
---|
17 | algDependent(I); computes algebraic relations between generators of I |
---|
18 | alg_kernel(phi); computes the kernel of the ringmap phi |
---|
19 | is_injective(phi); test for injectivity of ringmap phi |
---|
20 | is_surjective(phi); test for surjectivity of ringmap phi |
---|
21 | is_bijective(phi); test for bijectivity of ring map phi |
---|
22 | noetherNormal(id); noether normalization of ideal id |
---|
23 | mapIsFinite(R,phi,I); query for finiteness of map phi:R --> basering/I |
---|
24 | |
---|
25 | AUXILIARY PROCEDURES: |
---|
26 | finitenessTest(i,z); find variables which occur as pure power in lead(i) |
---|
27 | nonZeroEntry(id); list describing non-zero entries of an identifier |
---|
28 | "; |
---|
29 | |
---|
30 | LIB "inout.lib"; |
---|
31 | LIB "elim.lib"; |
---|
32 | LIB "ring.lib"; |
---|
33 | LIB "matrix.lib"; |
---|
34 | |
---|
35 | /////////////////////////////////////////////////////////////////////////////// |
---|
36 | |
---|
37 | proc algebra_containment (poly p, ideal A, list #) |
---|
38 | "USAGE: algebra_containment(p,A[,k]); p poly, A ideal, k integer. |
---|
39 | @* A = A[1],...,A[m] generators of subalgebra of the basering |
---|
40 | RETURN: |
---|
41 | @format |
---|
42 | - k=0 (or if k is not given) an integer: |
---|
43 | 1 : if p is contained in the subalgebra K[A[1],...,A[m]] |
---|
44 | 0 : if p is not contained in K[A[1],...,A[m]] |
---|
45 | - k=1 : a list, say l, of size 2, l[1] integer, l[2] ring, satisfying |
---|
46 | l[1]=1 if p is in the subalgebra K[A[1],...,A[m]] and then the ring |
---|
47 | l[2]: ring, contains poly check = h(y(1),...,y(m)) if p=h(A[1],...,A[m]) |
---|
48 | l[1]=0 if p is not in the subalgebra K[A[1],...,A[m]] and then |
---|
49 | l[2] contains the poly check = h(x,y(1),...,y(m)) if p satisfies |
---|
50 | the nonlinear relation p = h(x,A[1],...,A[m]) where |
---|
51 | x = x(1),...,x(n) denote the variables of the basering |
---|
52 | @end format |
---|
53 | DISPLAY: if k=0 and printlevel >= voice+1 (default) display the poly check |
---|
54 | NOTE: The proc inSubring uses a different algorithm which is sometimes |
---|
55 | faster. |
---|
56 | THEORY: The ideal of algebraic relations of the algebra generators A[1],..., |
---|
57 | A[m] is computed introducing new variables y(i) and the product |
---|
58 | order with x(i) >> y(i). |
---|
59 | p reduces to a polynomial only in the y(i) <=> p is contained in the |
---|
60 | subring generated by the polynomials A[1],...,A[m]. |
---|
61 | EXAMPLE: example algebra_containment; shows an example |
---|
62 | " |
---|
63 | { int DEGB = degBound; |
---|
64 | degBound = 0; |
---|
65 | if (size(#)==0) |
---|
66 | { #[1] = 0; |
---|
67 | } |
---|
68 | def br=basering; |
---|
69 | int n = nvars(br); |
---|
70 | int m = ncols(A); |
---|
71 | int i; |
---|
72 | string mp=string(minpoly); |
---|
73 | //----------------- |
---|
74 | // neu CL 10/05: |
---|
75 | int is_qring; |
---|
76 | if (size(ideal(br))>0) { |
---|
77 | is_qring=1; |
---|
78 | ideal IdQ = ideal(br); |
---|
79 | } |
---|
80 | //----------------- |
---|
81 | // ---------- create new ring with extra variables -------------------- |
---|
82 | execute ("ring R=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); |
---|
83 | execute ("minpoly=number("+mp+");"); |
---|
84 | ideal vars=x(1..n); |
---|
85 | map emb=br,vars; |
---|
86 | ideal A=ideal(emb(A)); |
---|
87 | poly check=emb(p); |
---|
88 | for (i=1;i<=m;i=i+1) |
---|
89 | { A[i]=A[i]-y(i); |
---|
90 | } |
---|
91 | //----------------- |
---|
92 | // neu CL 10/05: |
---|
93 | if (is_qring) { A = A,emb(IdQ); } |
---|
94 | //----------------- |
---|
95 | A=std(A); |
---|
96 | check=reduce(check,A); |
---|
97 | /*alternatively we could use reduce(check,A,1) which is a little faster |
---|
98 | but result is bigger since it is not tail-reduced |
---|
99 | */ |
---|
100 | //--- checking whether all variables from old ring have disappeared ------ |
---|
101 | // if so, then the sum of the first n leading exponents is 0, hence i=1 |
---|
102 | // use i also to control the display |
---|
103 | i = (sum(leadexp(check),1..n)==0); |
---|
104 | degBound = DEGB; |
---|
105 | if( #[1] == 0 ) |
---|
106 | { dbprint(printlevel-voice+3,"// "+string(check)); |
---|
107 | return(i); |
---|
108 | } |
---|
109 | else |
---|
110 | { list l = i,R; |
---|
111 | kill A,vars,emb; |
---|
112 | export check; |
---|
113 | dbprint(printlevel-voice+3," |
---|
114 | // 'algebra_containment' created a ring as 2nd element of the list. |
---|
115 | // The ring contains the poly check which defines the algebraic relation. |
---|
116 | // To access to the ring and see check you must give the ring a name, |
---|
117 | // e.g.: |
---|
118 | def S = l[2]; setring S; check; |
---|
119 | "); |
---|
120 | return(l); |
---|
121 | } |
---|
122 | } |
---|
123 | example |
---|
124 | { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; |
---|
125 | int p = printlevel; printlevel = 1; |
---|
126 | ring R = 0,(x,y,z),dp; |
---|
127 | ideal A=x2+y2,z2,x4+y4,1,x2z-1y2z,xyz,x3y-1xy3; |
---|
128 | poly p1=z; |
---|
129 | poly p2= |
---|
130 | x10z3-x8y2z3+2x6y4z3-2x4y6z3+x2y8z3-y10z3+x6z4+3x4y2z4+3x2y4z4+y6z4; |
---|
131 | algebra_containment(p1,A); |
---|
132 | algebra_containment(p2,A); |
---|
133 | list L = algebra_containment(p2,A,1); |
---|
134 | L[1]; |
---|
135 | def S = L[2]; setring S; |
---|
136 | check; |
---|
137 | printlevel = p; |
---|
138 | } |
---|
139 | /////////////////////////////////////////////////////////////////////////////// |
---|
140 | |
---|
141 | proc module_containment(poly p, ideal P, ideal S, list #) |
---|
142 | "USAGE: module_containment(p,P,M[,k]); p poly, P ideal, M ideal, k int |
---|
143 | @* P = P[1],...,P[n] generators of a subalgebra of the basering, |
---|
144 | @* M = M[1],...,M[m] generators of a module over the subalgebra K[P] |
---|
145 | ASSUME: ncols(P) = nvars(basering), the P[i] are algebraically independent |
---|
146 | RETURN: |
---|
147 | @format |
---|
148 | - k=0 (or if k is not given), an integer: |
---|
149 | 1 : if p is contained in the module <M[1],...,M[m]> over K[P] |
---|
150 | 0 : if p is not contained in <M[1],...,M[m]> |
---|
151 | - k=1, a list, say l, of size 2, l[1] integer, l[2] ring: |
---|
152 | l[1]=1 : if p is in <M[1],...,M[m]> and then the ring l[2] contains |
---|
153 | the polynomial check = h(y(1),...,y(m),z(1),...,z(n)) if |
---|
154 | p = h(M[1],...,M[m],P[1],...,P[n]) |
---|
155 | l[1]=0 : if p is in not in <M[1],...,M[m]>, then l[2] contains the |
---|
156 | poly check = h(x,y(1),...,y(m),z(1),...,z(n)) if p satisfies |
---|
157 | the nonlinear relation p = h(x,M[1],...,M[m],P[1],...,P[n]) where |
---|
158 | x = x(1),...,x(n) denote the variables of the basering |
---|
159 | @end format |
---|
160 | DISPLAY: the polynomial h(y(1),...,y(m),z(1),...,z(n)) if k=0, resp. |
---|
161 | a comment how to access the relation check if k=1, provided |
---|
162 | printlevel >= voice+1 (default). |
---|
163 | THEORY: The ideal of algebraic relations of all the generators p1,...,pn, |
---|
164 | s1,...,st given by P and S is computed introducing new variables y(j), |
---|
165 | z(i) and the product order: x^a*y^b*z^c > x^d*y^e*z^f if x^a > x^d |
---|
166 | with respect to the lp ordering or else if z^c > z^f with respect to |
---|
167 | the dp ordering or else if y^b > y^e with respect to the lp ordering |
---|
168 | again. p reduces to a polynomial only in the y(j) and z(i), linear in |
---|
169 | the z(i) <=> p is contained in the module. |
---|
170 | EXAMPLE: example module_containment; shows an example |
---|
171 | " |
---|
172 | { def br=basering; |
---|
173 | int DEGB = degBound; |
---|
174 | degBound=0; |
---|
175 | if (size(#)==0) |
---|
176 | { #[1] = 0; |
---|
177 | } |
---|
178 | int n=nvars(br); |
---|
179 | if ( ncols(P)==n ) |
---|
180 | { int m=ncols(S); |
---|
181 | string mp=string(minpoly); |
---|
182 | // ---------- create new ring with extra variables -------------------- |
---|
183 | execute |
---|
184 | ("ring R=("+charstr(br)+"),(x(1..n),y(1..m),z(1..n)),(lp(n),dp(m),lp(n));"); |
---|
185 | execute ("minpoly=number("+mp+");"); |
---|
186 | ideal vars = x(1..n); |
---|
187 | map emb = br,vars; |
---|
188 | ideal P = emb(P); |
---|
189 | ideal S = emb(S); |
---|
190 | poly check = emb(p); |
---|
191 | ideal I; |
---|
192 | for (int i=1;i<=m;i=i+1) |
---|
193 | { I[i]=S[i]-y(i); |
---|
194 | } |
---|
195 | for (i=1;i<=n;i=i+1) |
---|
196 | { I[m+i]=P[i]-z(i); |
---|
197 | } |
---|
198 | I=std(I); |
---|
199 | check = reduce(check,I); |
---|
200 | //--- checking whether all variables from old ring have disappeared ------ |
---|
201 | // if so, then the sum of the first n leading exponents is 0 |
---|
202 | i = (sum(leadexp(check),1..n)==0); |
---|
203 | if( #[1] == 0 ) |
---|
204 | { dbprint(i*(printlevel-voice+3),"// "+string(check)); |
---|
205 | return(i); |
---|
206 | } |
---|
207 | else |
---|
208 | { list l = i,R; |
---|
209 | kill I,vars,emb,P,S; |
---|
210 | export check; |
---|
211 | dbprint(printlevel-voice+3," |
---|
212 | // 'module_containment' created a ring as 2nd element of the list. The |
---|
213 | // ring contains the poly check which defines the algebraic relation |
---|
214 | // for p. To access to the ring and see check you must give the ring |
---|
215 | // a name, e.g.: |
---|
216 | def S = l[2]; setring S; check; |
---|
217 | "); |
---|
218 | return(l); |
---|
219 | } |
---|
220 | } |
---|
221 | else |
---|
222 | { "ERROR: the first ideal must have nvars(basering) entries"; |
---|
223 | return(); |
---|
224 | } |
---|
225 | } |
---|
226 | example |
---|
227 | { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; |
---|
228 | int p = printlevel; printlevel = 1; |
---|
229 | ring R=0,(x,y,z),dp; |
---|
230 | ideal P = x2+y2,z2,x4+y4; //algebra generators |
---|
231 | ideal M = 1,x2z-1y2z,xyz,x3y-1xy3; //module generators |
---|
232 | poly p1= |
---|
233 | x10z3-x8y2z3+2x6y4z3-2x4y6z3+x2y8z3-y10z3+x6z4+3x4y2z4+3x2y4z4+y6z4; |
---|
234 | module_containment(p1,P,M); |
---|
235 | poly p2=z; |
---|
236 | list l = module_containment(p2,P,M,1); |
---|
237 | l[1]; |
---|
238 | def S = l[2]; setring S; check; |
---|
239 | printlevel=p; |
---|
240 | } |
---|
241 | /////////////////////////////////////////////////////////////////////////////// |
---|
242 | |
---|
243 | proc inSubring(poly p, ideal I) |
---|
244 | "USAGE: inSubring(p,i); p poly, i ideal |
---|
245 | RETURN: |
---|
246 | @format |
---|
247 | a list l of size 2, l[1] integer, l[2] string |
---|
248 | l[1]=1 iff p is in the subring generated by i=i[1],...,i[k], |
---|
249 | and then l[2] = y(0)-h(y(1),...,y(k)) if p = h(i[1],...,i[k]) |
---|
250 | l[1]=0 iff p is in not the subring generated by i, |
---|
251 | and then l[2] = h(y(0),y(1),...,y(k) where p satisfies the |
---|
252 | nonlinear relation h(p,i[1],...,i[k])=0. |
---|
253 | @end format |
---|
254 | NOTE: the proc algebra_containment tests the same with a different |
---|
255 | algorithm, which is often faster |
---|
256 | EXAMPLE: example inSubring; shows an example |
---|
257 | " |
---|
258 | {int z=ncols(I); |
---|
259 | int i; |
---|
260 | def gnir=basering; |
---|
261 | int n = nvars(gnir); |
---|
262 | string mp=string(minpoly); |
---|
263 | list l; |
---|
264 | // neu CL 10/05: |
---|
265 | int is_qring; |
---|
266 | if (size(ideal(gnir))>0) { |
---|
267 | is_qring=1; |
---|
268 | ideal IdQ = ideal(gnir); |
---|
269 | } |
---|
270 | // ---------- create new ring with extra variables -------------------- |
---|
271 | //the intersection of ideal nett=(p-y(0),I[1]-y(1),...) |
---|
272 | //with the ring k[y(0),...,y(n)] is computed, the result is ker |
---|
273 | execute ("ring r1= ("+charstr(basering)+"),(x(1..n),y(0..z)),lp;"); |
---|
274 | // execute ("ring r1= ("+charstr(basering)+"),(y(0..z),x(1..n)),dp;"); |
---|
275 | execute ("minpoly=number("+mp+");"); |
---|
276 | ideal va = x(1..n); |
---|
277 | map emb = gnir,va; |
---|
278 | ideal nett = emb(I); |
---|
279 | for (i=1;i<=z;i++) |
---|
280 | { nett[i]=nett[i]-y(i); |
---|
281 | } |
---|
282 | nett=emb(p)-y(0),nett; |
---|
283 | // neu CL 10/05: |
---|
284 | if (is_qring) { nett = nett,emb(IdQ); } |
---|
285 | //----------------- |
---|
286 | ideal ker=eliminate(nett,product(va)); |
---|
287 | ker=std(ker); |
---|
288 | //---------- test wether y(0)-h(y(1),...,y(z)) is in ker -------------- |
---|
289 | l[1]=0; |
---|
290 | l[2]=""; |
---|
291 | for (i=1;i<=size(ker);i++) |
---|
292 | { if (deg(ker[i]/y(0))==0) |
---|
293 | { string str=string(ker[i]); |
---|
294 | setring gnir; |
---|
295 | l[1]=1; |
---|
296 | l[2]=str; |
---|
297 | return(l); |
---|
298 | } |
---|
299 | if (deg(ker[i]/y(0))>0) |
---|
300 | { l[2]=l[2]+string(ker[i]); |
---|
301 | } |
---|
302 | } |
---|
303 | return(l); |
---|
304 | } |
---|
305 | example |
---|
306 | { "EXAMPLE:"; echo = 2; |
---|
307 | ring q=0,(x,y,z,u,v,w),dp; |
---|
308 | poly p=xyzu2w-1yzu2w2+u4w2-1xu2vw+u2vw2+xyz-1yzw+2u2w-1xv+vw+2; |
---|
309 | ideal I =x-w,u2w+1,yz-v; |
---|
310 | inSubring(p,I); |
---|
311 | } |
---|
312 | ////////////////////////////////////////////////////////////////////////////// |
---|
313 | |
---|
314 | proc algDependent( ideal A, list # ) |
---|
315 | "USAGE: algDependent(f[,c]); f ideal (say, f = f1,...,fm), c integer |
---|
316 | RETURN: |
---|
317 | @format |
---|
318 | a list l of size 2, l[1] integer, l[2] ring: |
---|
319 | - l[1] = 1 if f1,...,fm are algebraic dependent, 0 if not |
---|
320 | - l[2] is a ring with variables x(1),...,x(n),y(1),...,y(m) if the |
---|
321 | basering has n variables. It contains the ideal 'ker', depending |
---|
322 | only on the y(i) and generating the algebraic relations between the |
---|
323 | f[i], i.e. substituting y(i) by fi yields 0. Of course, ker is |
---|
324 | nothing but the kernel of the ring map |
---|
325 | K[y(1),...,y(m)] ---> basering, y(i) --> fi. |
---|
326 | @end format |
---|
327 | NOTE: Three different algorithms are used depending on c = 1,2,3. |
---|
328 | If c is not given or c=0, a heuristically best method is choosen. |
---|
329 | The basering may be a quotient ring. |
---|
330 | To access to the ring l[2] and see ker you must give the ring a name, |
---|
331 | e.g. def S=l[2]; setring S; ker; |
---|
332 | DISPLAY: The above comment is displayed if printlevel >= 0 (default). |
---|
333 | EXAMPLE: example algDependent; shows an example |
---|
334 | " |
---|
335 | { |
---|
336 | int bestoption = 3; |
---|
337 | // bestoption is the default algorithm, it may be set to 1,2 or 3; |
---|
338 | // it should be changed, if another algorithm turns out to be faster |
---|
339 | // in general. Is perhaps dependent on the input (# vars, size ...) |
---|
340 | int tt; |
---|
341 | if( size(#) > 0 ) |
---|
342 | { if( typeof(#[1]) == "int" ) |
---|
343 | { tt = #[1]; |
---|
344 | } |
---|
345 | } |
---|
346 | if( size(#) == 0 or tt == 0 ) |
---|
347 | { tt = bestoption; |
---|
348 | } |
---|
349 | def br=basering; |
---|
350 | int n = nvars(br); |
---|
351 | ideal B = ideal(br); |
---|
352 | int m = ncols(A); |
---|
353 | int s = size(B); |
---|
354 | int i; |
---|
355 | string mp = string(minpoly); |
---|
356 | // --------------------- 1st variant of algorithm ---------------------- |
---|
357 | // use internal preimage command (should be equivalent to 2nd variant) |
---|
358 | if ( tt == 1 ) |
---|
359 | { |
---|
360 | execute ("ring R1=("+charstr(br)+"),y(1..m),dp;"); |
---|
361 | execute ("minpoly=number("+mp+");"); |
---|
362 | setring br; |
---|
363 | map phi = R1,A; |
---|
364 | setring R1; |
---|
365 | ideal ker = preimage(br,phi,B); |
---|
366 | } |
---|
367 | // ---------- create new ring with extra variables -------------------- |
---|
368 | execute ("ring R2=("+charstr(br)+"),(x(1..n),y(1..m)),(dp);"); |
---|
369 | execute ("minpoly=number("+mp+");"); |
---|
370 | if( tt == 1 ) |
---|
371 | { |
---|
372 | ideal ker = imap(R1,ker); |
---|
373 | } |
---|
374 | else |
---|
375 | { |
---|
376 | ideal vars = x(1..n); |
---|
377 | map emb = br,vars; |
---|
378 | ideal A = emb(A); |
---|
379 | for (i=1; i<=m; i=i+1) |
---|
380 | { A[i] = A[i]-y(i); |
---|
381 | } |
---|
382 | // --------------------- 2nd variant of algorithm ---------------------- |
---|
383 | // use internal eliminate for eliminating m variables x(i) from |
---|
384 | // ideal A[i] - y(i) (uses extra eliminating 'first row', a-order) |
---|
385 | if ( s == 0 and tt == 2 ) |
---|
386 | { ideal ker = eliminate(A,product(vars)); |
---|
387 | } |
---|
388 | else |
---|
389 | // eliminate does not work in qrings |
---|
390 | // --------------------- 3rd variant of algorithm ---------------------- |
---|
391 | // eliminate m variables x(i) from ideal A[i] - y(i) by choosing product |
---|
392 | // order |
---|
393 | {execute ("ring R3=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); |
---|
394 | execute ("minpoly=number("+mp+");"); |
---|
395 | if ( s != 0 ) |
---|
396 | { ideal vars = x(1..n); |
---|
397 | map emb = br,vars; |
---|
398 | ideal B = emb(B); |
---|
399 | attrib(B,"isSB",1); |
---|
400 | qring Q = B; |
---|
401 | } |
---|
402 | ideal A = imap(R2,A); |
---|
403 | A = std(A); |
---|
404 | ideal ker = nselect(A,1..n); |
---|
405 | setring R2; |
---|
406 | if ( defined(Q)==voice ) |
---|
407 | { ideal ker = imap(Q,ker); |
---|
408 | } |
---|
409 | else |
---|
410 | { ideal ker = imap(R3,ker); |
---|
411 | } |
---|
412 | kill A,emb,vars; |
---|
413 | } |
---|
414 | } |
---|
415 | // --------------------------- return ---------------------------------- |
---|
416 | s = size(ker); |
---|
417 | list L = (s!=0), R2; |
---|
418 | export(ker); |
---|
419 | dbprint(printlevel-voice+3," |
---|
420 | // The 2nd element of the list l is a ring with variables x(1),...,x(n), |
---|
421 | // and y(1),...,y(m) if the basering has n variables and if the ideal |
---|
422 | // is f[1],...,f[m]. The ring contains the ideal ker which depends only |
---|
423 | // on the y(i) and generates the relations between the f[i]. |
---|
424 | // I.e. substituting y(i) by f[i] yields 0. |
---|
425 | // To access to the ring and see ker you must give the ring a name, |
---|
426 | // e.g.: |
---|
427 | def S = l[2]; setring S; ker; |
---|
428 | "); |
---|
429 | return (L); |
---|
430 | } |
---|
431 | example |
---|
432 | { "EXAMPLE:"; echo = 2; |
---|
433 | int p = printlevel; printlevel = 1; |
---|
434 | ring R = 0,(x,y,z,u,v,w),dp; |
---|
435 | ideal I = xyzu2w-1yzu2w2+u4w2-1xu2vw+u2vw2+xyz-1yzw+2u2w-1xv+vw+2, |
---|
436 | x-w, u2w+1, yz-v; |
---|
437 | list l = algDependent(I); |
---|
438 | l[1]; |
---|
439 | def S = l[2]; setring S; |
---|
440 | ker; |
---|
441 | printlevel = p; |
---|
442 | } |
---|
443 | ////////////////////////////////////////////////////////////////////////////// |
---|
444 | proc alg_kernel( map phi, pr, list #) |
---|
445 | "USAGE: alg_kernel(phi,pr[,s,c]); phi map to basering, pr preimage ring, |
---|
446 | s string (name of kernel in pr), c integer. |
---|
447 | RETURN: a string, the kernel of phi as string. |
---|
448 | If, moreover, a string s is given, the algorithm creates, in the |
---|
449 | preimage ring pr the kernel of phi with name s. |
---|
450 | Three different algorithms are used depending on c = 1,2,3. |
---|
451 | If c is not given or c=0, a heuristically best method is chosen. |
---|
452 | (algorithm 1 uses the preimage command) |
---|
453 | NOTE: Since the kernel of phi lives in pr, it cannot be returned to the |
---|
454 | basering. If s is given, the user has access to it in pr via s. |
---|
455 | The basering may be a quotient ring. |
---|
456 | EXAMPLE: example alg_kernel; shows an example |
---|
457 | " |
---|
458 | { int tt; |
---|
459 | if( size(#) >0 ) |
---|
460 | { if( typeof(#[1]) == "int") |
---|
461 | { tt = #[1]; |
---|
462 | } |
---|
463 | if( typeof(#[1]) == "string") |
---|
464 | { string nker=#[1]; |
---|
465 | } |
---|
466 | if( size(#)>1 ) |
---|
467 | { if( typeof(#[2]) == "string") |
---|
468 | { string nker=#[2]; |
---|
469 | } |
---|
470 | if( typeof(#[2]) == "int") |
---|
471 | { tt = #[2]; |
---|
472 | } |
---|
473 | } |
---|
474 | } |
---|
475 | int n = nvars(basering); |
---|
476 | string mp = string(minpoly); |
---|
477 | ideal A = ideal(phi); |
---|
478 | //def pr = preimage(phi); |
---|
479 | //folgendes Auffuellen oder Stutzen ist ev nicht mehr noetig |
---|
480 | //falls map das richtig macht |
---|
481 | int m = nvars(pr); |
---|
482 | ideal j; |
---|
483 | j[m]=0; |
---|
484 | A=A,j; |
---|
485 | A=A[1..m]; |
---|
486 | list L = algDependent(A,tt); |
---|
487 | // algDependent is called with "bestoption" if tt = 0 |
---|
488 | def S = L[2]; |
---|
489 | execute ("ring R=("+charstr(basering)+"),(@(1..n),"+varstr(pr)+"),(dp);"); |
---|
490 | execute ("minpoly=number("+mp+");"); |
---|
491 | ideal ker = fetch(S,ker); //in order to have variable names correct |
---|
492 | string sker = string(ker); |
---|
493 | if (defined(nker) == voice) |
---|
494 | { setring pr; |
---|
495 | execute("ideal "+nker+"="+sker+";"); |
---|
496 | execute("export("+nker+");"); |
---|
497 | } |
---|
498 | return(sker); |
---|
499 | } |
---|
500 | example |
---|
501 | { "EXAMPLE:"; echo = 2; |
---|
502 | ring r = 0,(a,b,c),ds; |
---|
503 | ring s = 0,(x,y,z,u,v,w),dp; |
---|
504 | ideal I = x-w,u2w+1,yz-v; |
---|
505 | map phi = r,I; // a map from r to s: |
---|
506 | alg_kernel(phi,r); // a,b,c ---> x-w,u2w+1,yz-v |
---|
507 | |
---|
508 | ring S = 0,(a,b,c),ds; |
---|
509 | ring R = 0,(x,y,z),dp; |
---|
510 | qring Q = std(x-y); |
---|
511 | ideal i = x, y, x2-y3; |
---|
512 | map phi = S,i; // a map to a quotient ring |
---|
513 | alg_kernel(phi,S,"ker",3); // uses algorithm 3 |
---|
514 | setring S; // you have access to kernel in preimage |
---|
515 | ker; |
---|
516 | } |
---|
517 | ////////////////////////////////////////////////////////////////////////////// |
---|
518 | |
---|
519 | proc is_injective( map phi, pr,list #) |
---|
520 | "USAGE: is_injective(phi,pr[,c,s]); phi map, pr preimage ring, c int, s string |
---|
521 | RETURN: |
---|
522 | @format |
---|
523 | - 1 (type int) if phi is injective, 0 if not (if s is not given). |
---|
524 | - If s is given, return a list l of size 2, l[1] int, l[2] ring: |
---|
525 | l[1] is 1 if phi is injective, 0 if not |
---|
526 | l[2] is a ring with variables x(1),...,x(n),y(1),...,y(m) if the |
---|
527 | basering has n variables and the map m components, it contains the |
---|
528 | ideal 'ker', depending only on the y(i), the kernel of the given map |
---|
529 | @end format |
---|
530 | NOTE: Three differnt algorithms are used depending on c = 1,2,3. |
---|
531 | If c is not given or c=0, a heuristically best method is choosen. |
---|
532 | The basering may be a quotient ring. However, if the preimage ring is |
---|
533 | a quotient ring, say pr = P/I, consider phi as a map from P and then |
---|
534 | the algorithm returns 1 if the kernel of phi is 0 mod I. |
---|
535 | To access to the ring l[2] and see ker you must give the ring a name, |
---|
536 | e.g. def S=l[2]; setring S; ker; |
---|
537 | DISPLAY: The above comment is displayed if printlevel >= 0 (default). |
---|
538 | EXAMPLE: example is_injective; shows an example |
---|
539 | " |
---|
540 | { def bsr = basering; |
---|
541 | int tt; |
---|
542 | if( size(#) >0 ) |
---|
543 | { if( typeof(#[1]) == "int") |
---|
544 | { tt = #[1]; |
---|
545 | } |
---|
546 | if( typeof(#[1]) == "string") |
---|
547 | { string pau=#[1]; |
---|
548 | } |
---|
549 | if( size(#)>1 ) |
---|
550 | { if( typeof(#[2]) == "string") |
---|
551 | { string pau=#[2]; |
---|
552 | } |
---|
553 | if( typeof(#[2]) == "int") |
---|
554 | { tt = #[2]; |
---|
555 | } |
---|
556 | } |
---|
557 | } |
---|
558 | int n = nvars(basering); |
---|
559 | string mp = string(minpoly); |
---|
560 | ideal A = ideal(phi); |
---|
561 | //def pr = preimage(phi); |
---|
562 | //folgendes Auffuellen oder Stutzen ist ev nicht mehr noetig |
---|
563 | //falls map das richtig macht |
---|
564 | int m = nvars(pr); |
---|
565 | ideal j; |
---|
566 | j[m]=0; |
---|
567 | A=A,j; |
---|
568 | A=A[1..m]; |
---|
569 | list L = algDependent(A,tt); |
---|
570 | L[1] = L[1]==0; |
---|
571 | // the preimage ring may be a quotient ring, we still have to check whether |
---|
572 | // the kernel is 0 mod ideal of the quotient ring |
---|
573 | setring pr; |
---|
574 | if ( size(ideal(pr)) != 0 ) |
---|
575 | { def S = L[2]; |
---|
576 | ideal proj; |
---|
577 | proj [n+1..n+m] = maxideal(1); |
---|
578 | map psi = S,proj; |
---|
579 | L[1] = size(NF(psi(ker),std(0))) == 0; |
---|
580 | } |
---|
581 | if ( defined(pau) != voice ) |
---|
582 | { return (L[1]); |
---|
583 | } |
---|
584 | else |
---|
585 | { |
---|
586 | dbprint(printlevel-voice+3," |
---|
587 | // The 2nd element of the list is a ring with variables x(1),...,x(n), |
---|
588 | // y(1),...,y(m) if the basering has n variables and the map is |
---|
589 | // F[1],...,F[m]. |
---|
590 | // It contains the ideal ker, the kernel of the given map y(i) --> F[i]. |
---|
591 | // To access to the ring and see ker you must give the ring a name, |
---|
592 | // e.g.: |
---|
593 | def S = l[2]; setring S; ker; |
---|
594 | "); |
---|
595 | return(L); |
---|
596 | } |
---|
597 | } |
---|
598 | example |
---|
599 | { "EXAMPLE:"; echo = 2; |
---|
600 | int p = printlevel; |
---|
601 | ring r = 0,(a,b,c),ds; |
---|
602 | ring s = 0,(x,y,z,u,v,w),dp; |
---|
603 | ideal I = x-w,u2w+1,yz-v; |
---|
604 | map phi = r,I; // a map from r to s: |
---|
605 | is_injective(phi,r); // a,b,c ---> x-w,u2w+1,yz-v |
---|
606 | ring R = 0,(x,y,z),dp; |
---|
607 | ideal i = x, y, x2-y3; |
---|
608 | map phi = R,i; // a map from R to itself, z --> x2-y3 |
---|
609 | list l = is_injective(phi,R,""); |
---|
610 | l[1]; |
---|
611 | def S = l[2]; setring S; |
---|
612 | ker; |
---|
613 | } |
---|
614 | /////////////////////////////////////////////////////////////////////////////// |
---|
615 | |
---|
616 | proc is_surjective( map phi ) |
---|
617 | "USAGE: is_surjective(phi); phi map to basering, or ideal defining it |
---|
618 | RETURN: an integer, 1 if phi is surjective, 0 if not |
---|
619 | NOTE: The algorithm returns 1 iff all the variables of the basering are |
---|
620 | contained in the polynomial subalgebra generated by the polynomials |
---|
621 | defining phi. Hence, if the basering has local or mixed ordering |
---|
622 | or if the preimage ring is a quotient ring (in which case the map |
---|
623 | may not be well defined) then the return value 1 means \"surjectivity\" |
---|
624 | in this sense. |
---|
625 | EXAMPLE: example is_surjective; shows an example |
---|
626 | " |
---|
627 | { |
---|
628 | def br=basering; |
---|
629 | ideal B = ideal(br); |
---|
630 | int s = size(B); |
---|
631 | int n = nvars(br); |
---|
632 | ideal A = ideal(phi); |
---|
633 | int m = ncols(A); |
---|
634 | int ii,t=1,1; |
---|
635 | string mp=string(minpoly); |
---|
636 | // ------------ create new ring with extra variables --------------------- |
---|
637 | execute ("ring R=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); |
---|
638 | execute ("minpoly=number("+mp+");"); |
---|
639 | ideal vars = x(1..n); |
---|
640 | map emb = br,vars; |
---|
641 | if ( s != 0 ) |
---|
642 | { ideal B = emb(B); |
---|
643 | attrib(B,"isSB",1); |
---|
644 | qring Q = B; |
---|
645 | ideal vars = x(1..n); |
---|
646 | map emb = br,vars; |
---|
647 | } |
---|
648 | ideal A = emb(A); |
---|
649 | for ( ii=1; ii<=m; ii++ ) |
---|
650 | { A[ii] = A [ii]-y(ii); |
---|
651 | } |
---|
652 | A=std(A); |
---|
653 | // ------------- check whether the x(i) are in the image ----------------- |
---|
654 | poly check; |
---|
655 | for (ii=1; ii<=n; ii++ ) |
---|
656 | { check=reduce(x(ii),A,1); |
---|
657 | // --- checking whether all variables from old ring have disappeared ----- |
---|
658 | // if so, then the sum of the first n leading exponents is 0 |
---|
659 | if( sum(leadexp(check),1..n)!=0 ) |
---|
660 | { t=0; |
---|
661 | break; |
---|
662 | } |
---|
663 | } |
---|
664 | return(t); |
---|
665 | } |
---|
666 | example |
---|
667 | { "EXAMPLE:"; echo = 2; |
---|
668 | ring R = 0,(x,y,z),dp; |
---|
669 | ideal i = x, y, x2-y3; |
---|
670 | map phi = R,i; // a map from R to itself, z->x2-y3 |
---|
671 | is_surjective(phi); |
---|
672 | qring Q = std(ideal(z-x37)); |
---|
673 | map psi = R, x,y,x2-y3; // the same map to the quotient ring |
---|
674 | is_surjective(psi); |
---|
675 | |
---|
676 | ring S = 0,(a,b,c),dp; |
---|
677 | map psi = R,ideal(a,a+b,c-a2+b3); // a map from R to S, |
---|
678 | is_surjective(psi); // x->a, y->a+b, z->c-a2+b3 |
---|
679 | } |
---|
680 | |
---|
681 | /////////////////////////////////////////////////////////////////////////////// |
---|
682 | |
---|
683 | proc is_bijective ( map phi, pr ) |
---|
684 | "USAGE: is_bijective(phi,pr); phi map to basering, pr preimage ring |
---|
685 | RETURN: an integer, 1 if phi is bijective, 0 if not |
---|
686 | NOTE: The algorithm checks first injectivity and then surjectivity |
---|
687 | To interprete this for local/mixed orderings, or for quotient rings |
---|
688 | type help is_surjective; and help is_injective; |
---|
689 | DISPLAY: A comment if printlevel >= voice-1 (default) |
---|
690 | EXAMPLE: example is_bijective; shows an example |
---|
691 | " |
---|
692 | { |
---|
693 | def br = basering; |
---|
694 | int n = nvars(br); |
---|
695 | ideal B = ideal(br); |
---|
696 | int s = size(B); |
---|
697 | ideal A = ideal(phi); |
---|
698 | //folgendes Auffuellen oder Stutzen ist ev nicht mehr noetig |
---|
699 | //falls map das richtig macht |
---|
700 | int m = nvars(pr); |
---|
701 | ideal j; |
---|
702 | j[m]=0; |
---|
703 | A=A,j; |
---|
704 | A=A[1..m]; |
---|
705 | int ii,t = 1,1; |
---|
706 | string mp=string(minpoly); |
---|
707 | // ------------ create new ring with extra variables --------------------- |
---|
708 | execute ("ring R=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); |
---|
709 | execute ("minpoly=number("+mp+");"); |
---|
710 | ideal vars = x(1..n); |
---|
711 | map emb = br,vars; |
---|
712 | if ( s != 0 ) |
---|
713 | { ideal B = emb(B); |
---|
714 | attrib(B,"isSB",1); |
---|
715 | qring Q = B; |
---|
716 | ideal vars = x(1..n); |
---|
717 | map emb = br,vars; |
---|
718 | } |
---|
719 | ideal A = emb(A); |
---|
720 | for ( ii=1; ii<=m; ii++ ) |
---|
721 | { A[ii] = A[ii]-y(ii); |
---|
722 | } |
---|
723 | A=std(A); |
---|
724 | def bsr = basering; |
---|
725 | // ------- checking whether phi is injective by computing the kernel ------- |
---|
726 | ideal ker = nselect(A,1..n); |
---|
727 | t = size(ker); |
---|
728 | setring pr; |
---|
729 | if ( size(ideal(pr)) != 0 ) |
---|
730 | { |
---|
731 | ideal proj; |
---|
732 | proj[n+1..n+m] = maxideal(1); |
---|
733 | map psi = bsr,proj; |
---|
734 | t = size(NF(psi(ker),std(0))); |
---|
735 | } |
---|
736 | if ( t != 0 ) |
---|
737 | { dbprint(printlevel-voice+3,"// map not injective" ); |
---|
738 | return(0); |
---|
739 | } |
---|
740 | else |
---|
741 | // -------------- checking whether phi is surjective ---------------------- |
---|
742 | { t = 1; |
---|
743 | setring bsr; |
---|
744 | poly check; |
---|
745 | for (ii=1; ii<=n; ii++ ) |
---|
746 | { check=reduce(x(ii),A,1); |
---|
747 | // --- checking whether all variables from old ring have disappeared ----- |
---|
748 | // if so, then the sum of the first n leading exponents is 0 |
---|
749 | if( sum(leadexp(check),1..n)!=0 ) |
---|
750 | { t=0; |
---|
751 | break; |
---|
752 | } |
---|
753 | } |
---|
754 | if ( t == 0 ) |
---|
755 | { dbprint(printlevel-voice+3,"// map injective, but not surjective" ); |
---|
756 | } |
---|
757 | return(t); |
---|
758 | } |
---|
759 | } |
---|
760 | example |
---|
761 | { "EXAMPLE:"; echo = 2; |
---|
762 | int p = printlevel; printlevel = 1; |
---|
763 | ring R = 0,(x,y,z),dp; |
---|
764 | ideal i = x, y, x2-y3; |
---|
765 | map phi = R,i; // a map from R to itself, z->x2-y3 |
---|
766 | is_bijective(phi,R); |
---|
767 | qring Q = std(z-x2+y3); |
---|
768 | is_bijective(ideal(x,y,x2-y3),Q); |
---|
769 | |
---|
770 | ring S = 0,(a,b,c,d),dp; |
---|
771 | map psi = R,ideal(a,a+b,c-a2+b3,0); // a map from R to S, |
---|
772 | is_bijective(psi,R); // x->a, y->a+b, z->c-a2+b3 |
---|
773 | qring T = std(d,c-a2+b3); |
---|
774 | map chi = Q,a,b,a2-b3; // amap between two quotient rings |
---|
775 | is_bijective(chi,Q); |
---|
776 | |
---|
777 | printlevel = p; |
---|
778 | } |
---|
779 | /////////////////////////////////////////////////////////////////////////////// |
---|
780 | |
---|
781 | proc noetherNormal(ideal i, list #) |
---|
782 | "USAGE: noetherNormal(id[,p]); id ideal, p integer |
---|
783 | RETURN: |
---|
784 | @format |
---|
785 | a list l of two ideals, say I,J: |
---|
786 | - I is generated by a subset of the variables with size(I) = dim(id) |
---|
787 | - J defines a map (coordinate change in the basering), such that: |
---|
788 | if we define map phi=basering,J; |
---|
789 | then k[var(1),...,var(n)]/phi(id) is finite over k[I]. |
---|
790 | If p is given, 0<=p<=100, a sparse coordinate change with p percent |
---|
791 | of the matrix entries being 0 (default: p=0 i.e. dense) |
---|
792 | @end format |
---|
793 | NOTE: Designed for characteristic 0.It works also in char k > 0 if it |
---|
794 | terminates,but may result in an infinite loop in small characteristic |
---|
795 | EXAMPLE: example noetherNormal; shows an example |
---|
796 | " |
---|
797 | { |
---|
798 | if ( deg(i[1]) <= 0) |
---|
799 | { |
---|
800 | list l = ideal(0),i; |
---|
801 | return( l ); |
---|
802 | } |
---|
803 | int p; |
---|
804 | if( size(#) != 0 ) |
---|
805 | { |
---|
806 | p = #[1]; |
---|
807 | } |
---|
808 | def r = basering; |
---|
809 | int n = nvars(r); |
---|
810 | list good; |
---|
811 | // ------------------------ change of ordering --------------------------- |
---|
812 | //a procedure from ring.lib changing the order to dp creating a new |
---|
813 | //basering @R in order to compute the dimension d of i |
---|
814 | def @R=changeord("dp"); |
---|
815 | setring @R; |
---|
816 | ideal i = imap(r,i); |
---|
817 | list j = mstd(i); |
---|
818 | i = j[2]; |
---|
819 | int d = dim(j[1]); |
---|
820 | if ( d == 0) |
---|
821 | { |
---|
822 | setring r; |
---|
823 | list l = ideal(0),maxideal(1); |
---|
824 | return( l ); |
---|
825 | } |
---|
826 | // ------------------------ change of ordering --------------------------- |
---|
827 | //Now change the order to (dp(n-d),lp) creating a new basering @S |
---|
828 | string s ="dp("+string(n-d)+"),lp"; |
---|
829 | def @S=changeord(s); |
---|
830 | setring @S; |
---|
831 | ideal m; |
---|
832 | |
---|
833 | // ----------------- sparse-random coordinate change -------------------- |
---|
834 | //creating lower triangular random generators for the maximal ideal |
---|
835 | //a procedure from random.lib, as sparse as possible |
---|
836 | if( char(@S) > 0 ) |
---|
837 | { |
---|
838 | m=ideal(sparsetriag(n,n,p,char(@S)+1)*transpose(maxideal(1))); |
---|
839 | } |
---|
840 | if( char(@S) == 0 ) |
---|
841 | { |
---|
842 | if ( voice <= 6 ) |
---|
843 | { |
---|
844 | m=ideal(sparsetriag(n,n,p,10)*transpose(maxideal(1))); |
---|
845 | } |
---|
846 | if( voice > 6 and voice <= 11) |
---|
847 | { |
---|
848 | m=ideal(sparsetriag(n,n,p,100)*transpose(maxideal(1))); |
---|
849 | } |
---|
850 | if ( voice > 11 ) |
---|
851 | { |
---|
852 | m=ideal(sparsetriag(n,n,p,30000)*transpose(maxideal(1))); |
---|
853 | } |
---|
854 | } |
---|
855 | |
---|
856 | map phi=r,m; |
---|
857 | //map phi=@R,m; |
---|
858 | ideal i=std(phi(i)); |
---|
859 | |
---|
860 | // ----------------------- test for finiteness --------------------------- |
---|
861 | //We need a test whether the coordinate change was random enough, if yes |
---|
862 | //we are ready, else call noetherNormal again |
---|
863 | list l=finitenessTest(i); |
---|
864 | |
---|
865 | setring r; |
---|
866 | list l=imap(@S,l); |
---|
867 | |
---|
868 | if(size(l[3]) == d) //the generic case |
---|
869 | { |
---|
870 | good = fetch(@S,m),l[3]; |
---|
871 | kill @S,@R; |
---|
872 | return(good); |
---|
873 | } |
---|
874 | else //the bad case |
---|
875 | { kill @S,@R; |
---|
876 | if ( voice >= 21 ) |
---|
877 | { |
---|
878 | "// WARNING: In case of a finite ground field"; |
---|
879 | "// the characteristic may be too small."; |
---|
880 | "// This could result in an infinte loop."; |
---|
881 | "// Loop in noetherNormal, voice:";, voice;""; |
---|
882 | } |
---|
883 | if ( voice >= 16 ) |
---|
884 | { |
---|
885 | "// Switch to dense coordinate change";""; |
---|
886 | return(noetherNormal(i)); |
---|
887 | } |
---|
888 | return(noetherNormal(i,p)); |
---|
889 | } |
---|
890 | } |
---|
891 | example |
---|
892 | { "EXAMPLE:"; echo = 2; |
---|
893 | ring r=0,(x,y,z),dp; |
---|
894 | ideal i= xy,xz; |
---|
895 | noetherNormal(i); |
---|
896 | } |
---|
897 | /////////////////////////////////////////////////////////////////////////////// |
---|
898 | |
---|
899 | proc finitenessTest(ideal i, list #) |
---|
900 | "USAGE: finitenessTest(J[,v]); J ideal, v intvec (say v1,...,vr with vi>0) |
---|
901 | RETURN: |
---|
902 | @format |
---|
903 | a list l with l[1] integer, l[2], l[3], l[4] ideals |
---|
904 | - l[1] = 1 if var(v1),...,var(vr) are in l[2] and 0 else |
---|
905 | - l[2] (resp. l[3]) contains those variables which occur, |
---|
906 | (resp. do not occur) as pure power in the leading term of one of the |
---|
907 | generators of J, |
---|
908 | - l[4] contains those J[i] for which the leading term is a pure power |
---|
909 | of a variable (which is then in l[2]) |
---|
910 | (default: v = [1,2,..,nvars(basering)]) |
---|
911 | @end format |
---|
912 | THEORY: If J is a standard basis of an ideal generated by x_1 - f_1(y),..., |
---|
913 | x_n - f_n with y_j ordered lexicographically and y_j >> x_i, then, |
---|
914 | if y_i appears as pure power in the leading term of J[k], J[k] defines |
---|
915 | an integral relation for y_i over the y_(i+1),... and the f's. |
---|
916 | Moreover, in this situation, if l[2] = y_1,...,y_r, then K[y_1,...y_r] |
---|
917 | is finite over K[f_1..f_n]. If J contains furthermore polynomials |
---|
918 | h_j(y), then K[y_1,...y_z]/<h_j> is finite over K[f_1..f_n]. |
---|
919 | For a proof cf. Prop. 3.1.5, p. 214. in [G.-M. Greuel, G. Pfister: |
---|
920 | A SINGULAR Introduction to Commutative Algebra, 2nd Edition, |
---|
921 | Springer Verlag (2007)] |
---|
922 | EXAMPLE: example finitenessTest; shows an example |
---|
923 | " |
---|
924 | { int n = nvars(basering); |
---|
925 | intvec v,w; |
---|
926 | int j,z,ii; |
---|
927 | v[n]=0; //v should have size n |
---|
928 | intvec V = 1..n; |
---|
929 | list nze; //the non-zero entries of a leadexp |
---|
930 | if (size(#) != 0 ) |
---|
931 | { |
---|
932 | V = #[1]; |
---|
933 | } |
---|
934 | intmat W[1][n]; //create intmat with 1 row, having 1 at |
---|
935 | //position V[j], i = 1..size(V), 0 else |
---|
936 | for( j=1; j<=size(V); j++ ) |
---|
937 | { |
---|
938 | W[1,V[j]] = 1; |
---|
939 | } |
---|
940 | ideal relation,zero,nonzero; |
---|
941 | // ---------------------- check leading exponents ------------------------- |
---|
942 | |
---|
943 | for(j=1;j<=ncols(i);j++) |
---|
944 | { |
---|
945 | w = leadexp(i[j]); |
---|
946 | nze = nonZeroEntry(w); |
---|
947 | if( nze[1] == 1 ) //the leading term of i[j] is a |
---|
948 | { //pure power of some variable |
---|
949 | if( W*w != 0 ) //case: variable has index appearing in V |
---|
950 | { |
---|
951 | relation[size(relation)+1] = i[j]; |
---|
952 | v=v+w; |
---|
953 | } |
---|
954 | } |
---|
955 | } |
---|
956 | // ----------------- pick the corresponding variables --------------------- |
---|
957 | //the nonzero entries of v correspond to variables which occur as |
---|
958 | //pure power in the leading term of some polynomial in i |
---|
959 | |
---|
960 | for(j=1; j<=size(v); j++) |
---|
961 | { |
---|
962 | if(v[j]==0) |
---|
963 | { |
---|
964 | zero[size(zero)+1]=var(j); |
---|
965 | } |
---|
966 | else |
---|
967 | { |
---|
968 | nonzero[size(nonzero)+1]=var(j); |
---|
969 | } |
---|
970 | } |
---|
971 | // ---------------- do we have all pure powers we want? ------------------- |
---|
972 | // test this by dividing the product of corresponding variables |
---|
973 | ideal max = maxideal(1); |
---|
974 | max = max[V]; |
---|
975 | z = (product(nonzero)/product(max) != 0); |
---|
976 | return(list(z,nonzero,zero,relation)); |
---|
977 | } |
---|
978 | example |
---|
979 | { "EXAMPLE:"; echo = 2; |
---|
980 | ring s = 0,(x,y,z,a,b,c),(lp(3),dp); |
---|
981 | ideal i= a -(xy)^3+x2-z, b -y2-1, c -z3; |
---|
982 | ideal j = a -(xy)^3+x2-z, b -y2-1, c -z3, xy; |
---|
983 | finitenessTest(std(i),1..3); |
---|
984 | finitenessTest(std(j),1..3); |
---|
985 | } |
---|
986 | /////////////////////////////////////////////////////////////////////////////// |
---|
987 | |
---|
988 | proc mapIsFinite(map phi, R, list #) |
---|
989 | "USAGE: mapIsFinite(phi,R[,J]); R the preimage ring of the map |
---|
990 | phi: R ---> basering |
---|
991 | J an ideal in the basering, J = 0 if not given |
---|
992 | RETURN: 1 if R ---> basering/J is finite and 0 else |
---|
993 | NOTE: R may be a quotient ring (this will be ignored since a map R/I-->S/J |
---|
994 | is finite iff the induced map R-->S/J is finite). |
---|
995 | SEE ALSO: finitenessTest |
---|
996 | EXAMPLE: example mapIsFinite; shows an example |
---|
997 | " |
---|
998 | { |
---|
999 | def bsr = basering; |
---|
1000 | ideal J; |
---|
1001 | if( size(#) != 0 ) |
---|
1002 | { |
---|
1003 | J = #[1]; |
---|
1004 | } |
---|
1005 | string os = ordstr(bsr); |
---|
1006 | int m = nvars(bsr); |
---|
1007 | int n = nvars(R); |
---|
1008 | ideal PHI = ideal(phi); |
---|
1009 | if ( ncols(PHI) < n ) |
---|
1010 | { PHI[n]=0; |
---|
1011 | } |
---|
1012 | // --------------------- change of variable names ------------------------- |
---|
1013 | execute("ring @bsr = ("+charstr(bsr)+"),y(1..m),("+os+");"); |
---|
1014 | ideal J = fetch(bsr,J); |
---|
1015 | ideal PHI = fetch(bsr,PHI); |
---|
1016 | |
---|
1017 | // --------------------------- enlarging ring ----------------------------- |
---|
1018 | execute("ring @rr = ("+charstr(bsr)+"),(y(1..m),x(1..n)),(lp(m),dp);"); |
---|
1019 | ideal J = imap(@bsr,J); |
---|
1020 | ideal PHI = imap(@bsr,PHI); |
---|
1021 | ideal M; |
---|
1022 | int i; |
---|
1023 | |
---|
1024 | for(i=1;i<=n;i++) |
---|
1025 | { |
---|
1026 | M[i]=x(i)-PHI[i]; |
---|
1027 | } |
---|
1028 | M = std(M+J); |
---|
1029 | // ----------------------- test for finiteness --------------------------- |
---|
1030 | list l = finitenessTest(M,1..m); |
---|
1031 | return(l[1]); |
---|
1032 | } |
---|
1033 | example |
---|
1034 | { "EXAMPLE:"; echo = 2; |
---|
1035 | ring r = 0,(a,b,c),dp; |
---|
1036 | ring s = 0,(x,y,z),dp; |
---|
1037 | ideal i= xy; |
---|
1038 | map phi= r,(xy)^3+x2+z,y2-1,z3; |
---|
1039 | mapIsFinite(phi,r,i); |
---|
1040 | } |
---|
1041 | ////////////////////////////////////////////////////////////////////////////// |
---|
1042 | |
---|
1043 | proc nonZeroEntry(id) |
---|
1044 | "USAGE: nonZeroEntry(id); id=object for which the test 'id[i]!=0', i=1,..,N, |
---|
1045 | N=size(id) (resp. ncols(id) for id of type ideal or module) |
---|
1046 | is defined (e.g. ideal, vector, list of polynomials, intvec,...) |
---|
1047 | RETURN: @format |
---|
1048 | a list, say l, with l[1] an integer, l[2], l[3] integer vectors: |
---|
1049 | - l[1] number of non-zero entries of id |
---|
1050 | - l[2] intvec of size l[1] with l[2][i]=i if id[i] != 0 |
---|
1051 | in case l[1]!=0 (and l[2]=0 if l[1]=0) |
---|
1052 | - l[3] intvec with l[3][i]=1 if id[i]!=0 and l[3][i]=0 else |
---|
1053 | @end format |
---|
1054 | NOTE: |
---|
1055 | EXAMPLE: example nonZeroEntry; shows an example |
---|
1056 | " |
---|
1057 | { |
---|
1058 | int ii,jj,N,n; |
---|
1059 | intvec v,V; |
---|
1060 | |
---|
1061 | if ( typeof(id) == "ideal" || typeof(id) == "module" ) |
---|
1062 | { |
---|
1063 | N = ncols(id); |
---|
1064 | } |
---|
1065 | else |
---|
1066 | { |
---|
1067 | N = size(id); |
---|
1068 | } |
---|
1069 | for ( ii=1; ii<=N; ii++ ) |
---|
1070 | { |
---|
1071 | V[ii] = 0; |
---|
1072 | if ( id[ii] != 0 ) |
---|
1073 | { |
---|
1074 | n++; |
---|
1075 | v=v,ii; //the first entry of v is always 0 |
---|
1076 | V[ii] = 1; |
---|
1077 | } |
---|
1078 | } |
---|
1079 | if ( size(v) > 1 ) //if id[ii] != 0 for at least one ii delete the first 0 |
---|
1080 | { |
---|
1081 | v = v[2..size(v)]; |
---|
1082 | } |
---|
1083 | |
---|
1084 | list l = n,v,V; |
---|
1085 | return(l); |
---|
1086 | } |
---|
1087 | example |
---|
1088 | { "EXAMPLE:"; echo = 2; |
---|
1089 | ring r = 0,(a,b,c),dp; |
---|
1090 | poly f = a3c+b3+c2+a; |
---|
1091 | intvec v = leadexp(f); |
---|
1092 | nonZeroEntry(v); |
---|
1093 | |
---|
1094 | intvec w; |
---|
1095 | list L = 37,0,f,v,w; |
---|
1096 | nonZeroEntry(L); |
---|
1097 | } |
---|
1098 | ////////////////////////////////////////////////////////////////////////////// |
---|
1099 | |
---|