source: git/Singular/LIB/primitiv.lib @ 0ae4ce

spielwiese
Last change on this file since 0ae4ce was 0ae4ce, checked in by Anne Frühbis-Krüger <anne@…>, 23 years ago
*anne: added category to libraries for "Commutative Algebra" git-svn-id: file:///usr/local/Singular/svn/trunk@4941 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.3 KB
Line 
1// $Id: primitiv.lib,v 1.12 2000-12-19 14:41:45 anne Exp $
2// last change:            12.08.99
3///////////////////////////////////////////////////////////////////////////////
4// This library is for Singular 1.2 or newer
5
6version="$Id: primitiv.lib,v 1.12 2000-12-19 14:41:45 anne Exp $";
7category="Commutative Algebra";
8info="
9LIBRARY:    primitiv.lib    PROCEDURES FOR FINDING A PRIMITIVE ELEMENT
10AUTHOR:     Martin Lamm,    email: lamm@mathematik.uni-kl.de
11PROCEDURES:
12 primitive(ideal i);   find minimal polynomial for a primitive element
13 primitive_extra(i);   find primitive element for two generators
14 splitring(f,R[,L]);   define ring extension with name R and switch to it
15";
16
17///////////////////////////////////////////////////////////////////////////////
18LIB "random.lib";
19///////////////////////////////////////////////////////////////////////////////
20
21proc primitive(ideal i)
22"USAGE:   primitive(i); i ideal of the following form:
23 Let k be the ground field of your basering, a_1,...,a_n algebraic over k, @*
24 m_1(x_1), m_2(x_1,x_2),...,m_n(x_1,...,x_n) polynomials in k such that    @*
25 m_j(a_1,...,a_(j-1),x_j) is minimal polynomial for a_j over k(a_1,...,a_(j-1))
26                                                        for all j=1,...,n.
27 Then i has to be generated by m_1,...,m_n.
28
29RETURN:  ideal j in k[x_n] such that
30 j[1] is minimal polynomial for a primitive element b of k(a_1,...,a_n)=k(b)
31         over k
32 j[2],...,j[n+1] polynomials in k[x_n] : j[i+1](b)=a_i for i=1,...,n
33NOTE:    the number of variables in the basering has to be exactly the number n
34         of given algebraic elements (and minimal polynomials).
35
36         If k has few elements it can be that no one of the linear combinations
37         of a_1,...,a_n is a primitive element. In this case `primitive'
38         returns the zero ideal. If this occurs use primitive_extra instead.
39SEE ALSO: primitive_extra
40KEYWORDS: primitive element
41EXAMPLE: example primitive;  shows an example
42"
43{
44 def altring=basering;
45 execute("ring deglexring=("+charstr(altring)+"),("+varstr(altring)+"),dp;");
46 ideal j;
47 execute("ring lexring=("+charstr(altring)+"),("+varstr(altring)+"),lp;");
48 ideal i=fetch(altring,i);
49
50 int k,schlecht,Fehlversuche,maxtry;
51 int nva = nvars(basering);
52 int p=char(basering);
53 if (p==0) {
54   p=100000;
55   if (nva<3) { maxtry= 100000000; }
56   else       { maxtry=2147483647; }
57 }
58 else {
59   if ((nva<4) || (p<60)) {
60     maxtry=p^(nva-1); }
61   else {
62     maxtry=2147483647;          // int overflow(^)  vermeiden
63   }
64 }
65 ideal jmap,j;
66 map phi;
67 option(redSB);
68
69 //-------- Mache so lange Random-Koord.wechsel, bis letztes Poly -------------
70 //--------------- das Minpoly eines primitiven Elements ist : ----------------
71 for (Fehlversuche=0; Fehlversuche<maxtry; Fehlversuche++) {
72   schlecht=0;
73   if ((p<60) && (nva==2)) {  // systematische Suche statt random
74      jmap=ideal(var(1),var(2)+Fehlversuche*var(1));
75   }
76   else {
77    if (Fehlversuche==0) { jmap=maxideal(1);}
78    else {
79      if (Fehlversuche<5) { jmap=randomLast(10);}
80      else {
81       if (Fehlversuche<20) { jmap=randomLast(100);}
82       else                 { jmap=randomLast(100000000);}
83    }}                        // groessere Werte machen keinen Sinn
84   }
85   phi=lexring,jmap;
86   j=phi(i);
87   setring deglexring;
88 //--------------- Berechne reduzierte Standardbasis mit fglm: ----------------
89   j=std(fetch(lexring,j));
90   setring lexring;
91   j=fglm(deglexring,j);
92 //-- teste, ob SB n Elemente enthaelt (falls ja, ob lead(Fi)=xi i=1... n-1): -
93   if (size(j)==nva) {
94     for (k=1; k<nva; k++) {
95       j[k+1]=j[k+1]/leadcoef(j[k+1]);        // normiere die Erzeuger
96       if (lead(j[k+1]) != var(nva-k)) { schlecht=1;}
97     }
98     if (schlecht==0) {
99 //--- Random-Koord.wechsel war gut: Berechne das zurueckzugebende Ideal: -----
100       ideal erg;
101       for (k=1; k<nva; k++) { erg[k]=var(k)-j[nva-k+1]; }
102                               // =g_k(x_n) mit a_k=g_k(a_n)
103       erg[nva]=var(nva);
104       map chi=lexring,erg;
105       ideal extra=maxideal(1);extra=phi(extra);
106                               // sonst: "argument of a map must have a name"
107       erg=j[1],chi(extra);    // j[1] = Minimalpolynom
108       setring altring;
109       return(fetch(lexring,erg));
110     }
111   }
112   dbprint("The random coordinate change was bad!");
113 }
114 if (voice==2) {
115   "// ** Warning: No primitive element could be found.";
116   "//    If the given ideal really describes the minimal polynomials of";
117   "//    a series of algebraic elements (cf. `help primitive;') then";
118   "//    try `primitive_extra'.";
119 }
120 setring altring;
121 return(ideal(0));
122}
123example
124{ "EXAMPLE:"; echo = 2;
125 ring exring=0,(x,y),dp;
126 ideal i=x2+1,y2-x;                  // compute Q(i,i^(1/2))=:L
127 ideal j=primitive(i);               // -> we have L=Q(a):
128 "minimal polynomial of a:",j[1];    // => a=(-1)^(1/4)
129 "polynomial for i:       ",j[2];    // => i=a^2
130 "polynomial for i^(1/2): ",j[3];    // => i^(1/2)=a
131 // ==> the 2nd element was already primitive!
132 j=primitive(ideal(x2-2,y2-3));      // compute Q(sqrt(2),sqrt(3))
133 "minimal polynomial:",j[1];
134 "polynomial p s.t. p(a)=sqrt(2):",j[2];
135 "polynomial r s.t. r(a)=sqrt(3):",j[3];
136 // ==> no element was primitive -- the calculation of a is based
137 //     on a random choice.
138}
139///////////////////////////////////////////////////////////////////////////////
140
141proc primitive_extra(ideal i)
142"USAGE:   primitive_extra(i);  ideal i=f,g;  with the following properties: @*
143 Let k=Q or k=Z/pZ be the ground field of the basering, a,b algebraic over k,
144 x the name of the first ring variable, y the name of the second, then:     @*
145 f is the minimal polynomial of a in k[x], g is a polynomial in k[x,y] s.t.
146 g(a,y) is the minimal polynomial of b in k(a)[y]
147
148RETURN:  ideal j in k[y] such that
149 j[1] is minimal polynomial over k for a primitive element c of k(a,b)=k(c) @*
150 j[2] is a polynomial s.t. j[2](c)=a
151
152NOTE: - While `primitive' may fail for finite fields, this proc tries all
153        elements of k(a,b) and hence finds by assurance a primitive element.
154        In order to do this (try all elements) field extensions like Z/pZ(a)
155        are not allowed for the ground field k.
156      - primitive_extra assumes that g is monic as polynomial in (k[x])[y]
157EXAMPLE: example primitive_extra;  shows an example
158"
159{
160 def altring=basering;
161 int grad1,grad2=deg(i[1]),deg(jet(i[2],0,intvec(1,0)));
162 int countx,countz;
163 ring deglexring=char(altring),(x,y,z),dp;
164 map transfer=altring,x,z;
165 ideal i=transfer(i);
166 if (size(i)!=2) {
167   "//** Error -- either wrong number of given minimal polynomials";
168   "//**          or wrong choice of ring variables (must use the first two)";
169   setring altring;
170   return(ideal(0));
171 }
172 matrix mat;
173 ring lexring=char(altring),(x,y),lp;
174 ideal j;
175 ring deglex2ring=char(altring),(x,y),dp;
176 ideal j;
177 setring deglexring;
178 ideal j;
179 option(redSB);
180 poly g=z;
181 int found=0;
182
183 //---------------- Schleife zum Finden des primitiven Elements ---------------
184 //--- Schleife ist so angordnet, dass g in Charakteristik 0 linear bleibt ----
185 while (found==0) {
186   j=eliminate(i+ideal(g-y),z);
187   setring deglex2ring;
188   j=std(imap(deglexring,j));
189   setring lexring;
190   j=fglm(deglex2ring,j);
191   if (size(j)==2) {
192     if (deg(j[1])==grad1*grad2) {
193       j[2]=j[2]/leadcoef(j[2]);    // Normierung
194       if (lead(j[2])==x) {         // Alles ok
195          found=1;
196       }
197     }
198   }
199   setring deglexring;
200   if (found==0) {
201 //------------------ waehle ein neues Polynom g ------------------------------
202     dbprint("Still searching for primitive element...");
203     countx=0;
204     countz=0;
205     while (found==0) {
206      countx++;
207      if (countx>=grad1) {
208        countx=0;
209        countz++;
210        if (countz>=grad2) {
211         "//** Error: No primitive element found!! This should NEVER happen!";
212         setring altring;
213         return(ideal(0));
214        }
215      }
216      g = g +x^countx *z^countz;
217      mat=coeffs(g,z);
218      if (size(mat)>countz) {
219        mat=coeffs(mat[countz+1,1],x);
220        if (size(mat)>countx) {
221          if (mat[countx+1,1] != 0) {
222            found=1;         // d.h. hier: neues g gefunden
223      }}}
224     }
225     found=0;
226   }
227 }
228 //------------------- primitives Element gefunden; Rueckgabe -----------------
229 setring lexring;
230 j[2]=x-j[2];
231 setring altring;
232 map transfer=lexring,var(1),var(2);
233 return(transfer(j));
234}
235example
236{ "EXAMPLE:"; echo = 2;
237 ring exring=3,(x,y),dp;
238 ideal i=x2+1,y3+y2-1;
239 primitive_extra(i);
240 ring extension=(3,y),x,dp;
241 minpoly=y6-y5+y4-y3-y-1;
242 number a=y5+y4+y2+y+1;
243 a^2;
244 factorize(x2+1);
245 factorize(x3+x2-1);
246}
247///////////////////////////////////////////////////////////////////////////////
248
249proc splitring
250"USAGE:  splitring(f,R[,L]);  f poly, univariate and irreducible(!) over the
251         active basering; R string, L list of polys and/or ideals (optional)
252CREATE: a ring with name R, in which f is reducible, and change to it.
253        If the old ring has no parameter, the name 'a' is chosen for the
254        parameter of R (if a is no variable; if it is, the proc takes 'b',
255        etc.; if a,b,c,o are variables of the ring, produce an error message),
256        otherwise the name of the parameter is kept and only the
257        minimal polynomial is changed.
258        The names of variables and orderings are not affected.
259
260        It is also allowed to call splitring with R==\"\". Then the old basering
261        will be REPLACED by the new ring (with the same name as the old ring).
262
263RETURN: list L mapped into the new ring R, if L is given; else nothing
264ASSUME: The active ring must allow an algebraic extension
265         (e.g. it cannot be a transcendent ring extension of Q or Z/p).
266KEYWORDS: algebraic field extension; extension of rings
267EXAMPLE: example splitring;  shows an example
268"
269{
270 //----------------- split ist bereits eine proc in 'inout.lib' ! -------------
271 poly f=#[1]; string @R=#[2];
272 if (size(#)>2) {
273    list L=#[3];
274    int L_groesse=size(L);
275 }
276 else { int L_groesse=-1; }
277 //-------------- ermittle das Minimalpolynom des aktuellen Rings: ------------
278 string minp=string(minpoly);
279
280 if (@R=="") {
281  string altrname=nameof(basering);
282  @R="splt_temp";
283 }
284
285 def altring=basering;
286 string charakt=string(char(altring));
287 string varnames=varstr(altring);
288 string algname;
289 int i;
290 int anzvar=size(maxideal(1));
291 //--------------- Fall 1: Bisheriger Ring hatte kein Minimalpolynom ----------
292 if (minp=="0") {
293  if (find(varnames,"a")==0)        { algname="a";}
294  else { if (find(varnames,"b")==0) { algname="b";}
295         else { if (find(varnames,"c")==0)
296                                    { algname="c";}
297         else { if (find(varnames,"o")==0)
298                                    { algname="o";}
299         else {
300           "** Sorry -- could not find a free name for the primitive element.";
301           "** Try e.g. a ring without 'a' or 'b' as variable.";
302           return();
303         }}
304       }
305  }
306 //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: --
307  execute("ring splt1="+charakt+","+algname+",dp;");
308  ideal abbnach=var(1);
309  for (i=1; i<anzvar; i++) { abbnach=abbnach,var(1); }
310  map nach_splt1=altring,abbnach;
311  execute("poly mipol="+string(nach_splt1(f))+";");
312  string Rminp=string(mipol);
313 //--------------------- definiere den neuen Ring: ----------------------------
314  execute("ring "+@R+" = ("+charakt+","+algname+"),("+varnames+"),("
315           +ordstr(altring)+");");
316  execute("minpoly="+Rminp+";");
317  execute("export "+@R+";");
318  def neuring=basering;
319 //---------------------- Berechne die zurueckzugebende Liste: ----------------
320  list erg;
321  if (L_groesse>0) {
322 // L ist ja nicht in 'neuring' def., daher merke man sich die Groesse als int
323   map take=altring,maxideal(1);
324   erg=take(L);
325  }            // take(empty list) gibt nicht empty list, sondern Fehlermeldung
326 }
327 else {
328 //------------- Fall 2: Bisheriger Ring hatte ein Minimalpolynom: ------------
329  algname=parstr(altring);           // Name des algebraischen Elements
330  if (size(algname)>1) {"only one Parameter is allowed!!"; return();}
331 //---------------- Minimalpolynom in ein Polynom umwandeln: ------------------
332  execute("ring splt2="+charakt+","+algname+",dp;");
333  execute("poly mipol="+minp+";");
334 // f ist Polynom in algname und einer weiteren Variablen --> mache f bivariat:
335  execute("ring splt3="+charakt+",("+algname+","+varnames+"),dp;");
336  poly f=imap(altring,f);
337 //-------------- Vorbereitung des Aufrufes von primitive: --------------------
338  execute("ring splt1="+charakt+",(x,y),dp;");
339  ideal abbnach=x;
340  for (i=1; i<=anzvar; i++) { abbnach=abbnach,y; }
341  map nach_splt1_3=splt3,abbnach;
342  map nach_splt1_2=splt2,x;
343  ideal maxid=nach_splt1_2(mipol),nach_splt1_3(f);
344  ideal primit=primitive(maxid);
345  if (size(primit)==0) {             // Suche mit 1. Proc erfolglos
346    primit=primitive_extra(maxid);
347  }
348 //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: --
349  setring splt2;
350  map nach_splt2=splt1,0,var(1);     // x->0, y->a
351  minp=string(nach_splt2(primit)[1]);
352  if (printlevel > -1) { "// new minimal polynomial:",minp; }
353 //--------------------- definiere den neuen Ring: ----------------------------
354  execute("ring "+@R+" = ("+charakt+","+algname+"),("+varnames+"),("
355          +ordstr(altring)+");");
356  execute("minpoly="+minp+";");
357  execute("export "+@R+";");
358  def neuring=basering;
359
360 //--------------- Uebersicht: wenn altring=(p,a),(x,y),dp; dann: -------------
361 //------------ splt1=p,(x,y),dp;  splt2=p,a,dp;  splt3=p,(a,x,y),dp; ---------
362
363  list erg;
364  if (L_groesse>0) {
365 //---------------------- Berechne die zurueckzugebende Liste: ----------------
366    setring splt3;
367    list zwi=imap(altring,L);
368    map nach_splt3_1=splt1,0,var(1);  // x->0, y->a
369 //----- rechne das primitive Element von altring in das von neuring um: ------
370    ideal convid=maxideal(1);
371    convid[1]=nach_splt3_1(primit)[2];
372    map convert=splt3,convid;
373    zwi=convert(zwi);
374    setring neuring;
375    erg=imap(splt3,zwi);
376  }
377 }
378 if (defined(altrname)) {
379   if(system("with","Namespaces"))
380   { kill Top::`altrname`; kill Top::splt_temp; }
381   execute("kill "+altrname+";");
382   execute("def "+altrname+" = splt_temp;");
383   @R=altrname;
384   execute("export "+altrname+";");
385   kill splt_temp;
386 }
387
388 execute("keepring "+@R+";");
389 if (L_groesse >= 0) { return(erg); }
390}
391example
392{ "EXAMPLE:"; echo = 2;
393 ring r=0,(x,y),dp;
394 splitring(x2-2,"r1");   // change to Q(sqrt(2))
395 splitring(x2-a,"r2",a); // change to Q(sqrt(2),sqrt(sqrt(2)))=Q(a)
396                         // and return the transformed old parameter
397 // the result is (a2) == (sqrt(sqrt(2)))^2
398 nameof(basering);
399 r2;
400 kill r1; kill r2;
401}
Note: See TracBrowser for help on using the repository browser.