source: git/Singular/LIB/primitiv.lib @ f34c37c

spielwiese
Last change on this file since f34c37c was f34c37c, checked in by Olaf Bachmann <obachman@…>, 25 years ago
* cosmetic changes to enable parsing of help git-svn-id: file:///usr/local/Singular/svn/trunk@3233 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 14.3 KB
Line 
1// $Id: primitiv.lib,v 1.10 1999-07-06 11:33:10 obachman 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.10 1999-07-06 11:33:10 obachman Exp $";
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
21///////////////////////////////////////////////////////////////////////////////
22
23proc primitive(ideal i)
24"USAGE:   primitive(i); i ideal of the following form:
25 Let k be the ground field of your basering, a_1,...,a_n algebraic over k,
26 m_1(x_1), m_2(x_1,x_2),...,m_n(x_1,...,x_n) polynomials in k such that
27 m_j(a_1,...,a_(j-1),x_j) is minimal polynomial for a_j over k(a_1,...,a_(j-1))
28                                                        for all j=1,...,n.
29 Then i has to be generated by m_1,...,m_n.
30
31RETURN:  ideal j in k[x_n] such that
32 j[1] is minimal polynomial for a primitive element b of k(a_1,...,a_n)=k(b)
33         over k
34 j[2],...,j[n+1] polynomials in k[x_n] : j[i+1](b)=a_i for i=1,...,n
35NOTE:    the number of variables in the basering has to be exactly the number n
36         of given algebraic elements (and minimal polynomials).
37
38         If k has few elements it can be that no one of the linear combinations
39         of a_1,...,a_n is a primitive element. In this case `primitive'
40         returns the zero ideal. If this occurs use primitive_extra instead.
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 on a random
137 //     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, irreducible(!), R string,
251                     L list of polys and/or ideals (optional)
252CREATE: defines a ring with name R, in which f is reducible, and changes 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)
266EXAMPLE: example splitring;  shows an example
267"
268{
269 //----------------- split ist bereits eine proc in 'inout.lib' ! -------------
270 poly f=#[1]; string @R=#[2];
271 if (size(#)>2) {
272    list L=#[3];
273    int L_groesse=size(L);
274 }
275 else { int L_groesse=-1; }
276 //-------------- ermittle das Minimalpolynom des aktuellen Rings: ------------
277 string minp=string(minpoly);
278
279 if (@R=="") {
280  string altrname=nameof(basering);
281  @R="splt_temp";
282 }
283
284 def altring=basering;
285 string charakt=string(char(altring));
286 string varnames=varstr(altring);
287 string algname;
288 int i;
289 int anzvar=size(maxideal(1));
290 //--------------- Fall 1: Bisheriger Ring hatte kein Minimalpolynom ----------
291 if (minp=="0") {
292  if (find(varnames,"a")==0)        { algname="a";}
293  else { if (find(varnames,"b")==0) { algname="b";}
294         else { if (find(varnames,"c")==0)
295                                    { algname="c";}
296         else { if (find(varnames,"o")==0)
297                                    { algname="o";}
298         else {
299           "** Sorry -- could not find a free name for the primitive element.";
300           "** Try e.g. a ring without 'a' or 'b' as variable.";
301           return();
302         }}
303       }
304  }
305 //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: --
306  execute("ring splt1="+charakt+","+algname+",dp;");
307  ideal abbnach=var(1);
308  for (i=1; i<anzvar; i++) { abbnach=abbnach,var(1); }
309  map nach_splt1=altring,abbnach;
310  execute("poly mipol="+string(nach_splt1(f))+";");
311  string Rminp=string(mipol);
312 //--------------------- definiere den neuen Ring: ----------------------------
313  execute("ring "+@R+" = ("+charakt+","+algname+"),("+varnames+"),("
314           +ordstr(altring)+");");
315  execute("minpoly="+Rminp+";");
316  execute("export "+@R+";");
317  def neuring=basering;
318 //---------------------- Berechne die zurueckzugebende Liste: ----------------
319  list erg;
320  if (L_groesse>0) {
321 // L ist ja nicht in 'neuring' def., daher merke man sich die Groesse als int
322   map take=altring,maxideal(1);
323   erg=take(L);
324  }            // take(empty list) gibt nicht empty list, sondern Fehlermeldung
325 }
326 else {
327 //------------- Fall 2: Bisheriger Ring hatte ein Minimalpolynom: ------------
328  algname=parstr(altring);           // Name des algebraischen Elements
329  if (size(algname)>1) {"only one Parameter is allowed!!"; return();}
330 //---------------- Minimalpolynom in ein Polynom umwandeln: ------------------
331  execute("ring splt2="+charakt+","+algname+",dp;");
332  execute("poly mipol="+minp+";");
333 // f ist Polynom in algname und einer weiteren Variablen --> mache f bivariat:
334  execute("ring splt3="+charakt+",("+algname+","+varnames+"),dp;");
335  poly f=imap(altring,f);
336 //-------------- Vorbereitung des Aufrufes von primitive: --------------------
337  execute("ring splt1="+charakt+",(x,y),dp;");
338  ideal abbnach=x;
339  for (i=1; i<=anzvar; i++) { abbnach=abbnach,y; }
340  map nach_splt1_3=splt3,abbnach;
341  map nach_splt1_2=splt2,x;
342  ideal maxid=nach_splt1_2(mipol),nach_splt1_3(f);
343  ideal primit=primitive(maxid);
344  if (size(primit)==0) {             // Suche mit 1. Proc erfolglos
345    primit=primitive_extra(maxid);
346  }
347 //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: --
348  setring splt2;
349  map nach_splt2=splt1,0,var(1);     // x->0, y->a
350  minp=string(nach_splt2(primit)[1]);
351  "// new minimal polynomial:",minp;
352 //--------------------- definiere den neuen Ring: ----------------------------
353  execute("ring "+@R+" = ("+charakt+","+algname+"),("+varnames+"),("
354          +ordstr(altring)+");");
355  execute("minpoly="+minp+";");
356  execute("export "+@R+";");
357  def neuring=basering;
358
359 //--------------- Uebersicht: wenn altring=(p,a),(x,y),dp; dann: -------------
360 //------------ splt1=p,(x,y),dp;  splt2=p,a,dp;  splt3=p,(a,x,y),dp; ---------
361
362  list erg;
363  if (L_groesse>0) {
364 //---------------------- Berechne die zurueckzugebende Liste: ----------------
365    setring splt3;
366    list zwi=imap(altring,L);
367    map nach_splt3_1=splt1,0,var(1);  // x->0, y->a
368 //----- rechne das primitive Element von altring in das von neuring um: ------
369    ideal convid=maxideal(1);
370    convid[1]=nach_splt3_1(primit)[2];
371    map convert=splt3,convid;
372    zwi=convert(zwi);
373    setring neuring;
374    erg=imap(splt3,zwi);
375  }
376 }
377 if (defined(altrname)) {
378   if(system("with","Namespaces"))
379   { kill Top::`altrname`; kill Top::splt_temp; }
380   execute("kill "+altrname+";");
381   execute("def "+altrname+" = splt_temp;");
382   @R=altrname;
383   execute("export "+altrname+";");
384   kill splt_temp;
385 }
386
387 execute("keepring "+@R+";");
388 if (L_groesse >= 0) {return(erg);}
389}
390example
391{ "EXAMPLE:"; echo = 2;
392 ring r=0,(x,y),dp;
393 splitring(x2-2,"r1");   // change to Q(sqrt(2))
394 splitring(x2-a,"r2",a); // change to Q(sqrt(2),sqrt(sqrt(2)))=Q(a)
395                         // and return the transformed old parameter
396 // the result is (a2) == (sqrt(sqrt(2)))^2
397 nameof(basering);
398 r2;
399 kill r1; kill r2;
400}
Note: See TracBrowser for help on using the repository browser.