source: git/Singular/LIB/primitiv.lib @ 81fb58d

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