source: git/Singular/LIB/zeroset.lib @ c335c5

spielwiese
Last change on this file since c335c5 was c335c5, checked in by Hans Schönemann <hannes@…>, 15 years ago
*hannes: syntax fix git-svn-id: file:///usr/local/Singular/svn/trunk@11628 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 45.1 KB
RevLine 
[6fe3a0]1// Last change 12.02.2001 (Eric Westenberger)
[4e461ff]2///////////////////////////////////////////////////////////////////////////////
[c335c5]3version="$Id: zeroset.lib,v 1.20 2009-04-06 13:21:58 Singular Exp $";
[fd3fb7]4category="Symbolic-numerical solving";
[4e461ff]5info="
[0bc582c]6LIBRARY:  zeroset.lib      Procedures for roots and factorization
7AUTHOR:   Thomas Bayer,    email: tbayer@mathematik.uni-kl.de,@*
8          http://wwwmayr.informatik.tu-muenchen.de/personen/bayert/@*
9          Current address: Hochschule Ravensburg-Weingarten
[d12655]10
[b9b906]11OVERVIEW:
[9173792]12 Algorithms for finding the zero-set of a zero-dim. ideal in Q(a)[x_1,..,x_n],
[731e67e]13 roots and factorization of univariate polynomials over Q(a)[t]
14 where a is an algebraic number. Written in the scope of the
[b9b906]15 diploma thesis (advisor: Prof. Gert-Martin Greuel) 'Computations of moduli
[6fe3a0]16 spaces of semiquasihomogeneous singularities and an implementation in Singular'.
[d12655]17 This library is meant as a preliminary extension of the functionality
18 of Singular for univariate factorization of polynomials over simple algebraic
19 extensions in characteristic 0.
[c335c5]20
[0bc582c]21 NOTE:
[d12655]22 Subprocedures with postfix 'Main' require that the ring contains a variable
23 'a' and no parameters, and the ideal 'mpoly', where 'minpoly' from the
24 basering is stored.
[4e461ff]25
26PROCEDURES:
[c335c5]27 Quotient(f, g)    quotient q  of f w.r.t. g (in f = q*g + remainder)
[0bc582c]28 remainder(f,g)    remainder of the division of f by g
29 roots(f)    computes all roots of f in an extension field of Q
30 sqfrNorm(f)    norm of f (f must be squarefree)
31 zeroSet(I)    zero-set of the 0-dim. ideal I
[4e461ff]32
[d12655]33AUXILIARY PROCEDURES:
[0bc582c]34 egcdMain(f, g)    gcd over an algebraic extension field of Q
35 factorMain(f)    factorization of f over an algebraic extension field
36 invertNumberMain(c)  inverts an element of an algebraic extension field
37 quotientMain(f, g)  quotient of f w.r.t. g
38 remainderMain(f,g)  remainder of the division of f by g
39 rootsMain(f)    computes all roots of f, might extend the ground field
40 sqfrNormMain(f)  norm of f (f must be squarefree)
41 containedQ(data, f)  f in data ?
42 sameQ(a, b)    a == b (list a,b)
[4e461ff]43";
44
[d12655]45LIB "primitiv.lib";
46LIB "primdec.lib";
[4e461ff]47
48// note : return a ring : ring need not be exported !!!
[6fe3a0]49
50// Artihmetic in Q(a)[x] without built-in procedures
[4e461ff]51// assume basering = Q[x,a] and minpoly is represented by mpoly(a).
[6fe3a0]52// the algorithms are taken from "Polynomial Algorithms in Computer Algebra",
[4e461ff]53// F. Winkler, Springer Verlag Wien, 1996.
54
55
56// To do :
[d12655]57// squarefree factorization
[4e461ff]58// multiplicities
59
60// Improvement :
[0bc582c]61// a main problem is the growth of the coefficients. Try roots(x7 - 1)
[9173792]62// return ideal mpoly !
[4e461ff]63// mpoly is not monic, comes from primitive_extra
64
[d12655]65// IMPLEMENTATION
[4e461ff]66//
67// In procedures with name 'proc-name'Main a polynomial ring over a simple
68// extension field is represented as Q[x...,a] together with the ideal
69// 'mpoly' (attribute "isSB"). The arithmetic in the extension field is
[6fe3a0]70// implemented in the procedures in the procedures 'MultPolys' (multiplication)
[d12655]71// and 'InvertNumber' (inversion). After addition and substraction one should
[4e461ff]72// apply 'SimplifyPoly' to the result to reduce the result w.r.t. 'mpoly'.
[d12655]73// This is done by reducing each coefficient seperately, which is more
[4e461ff]74// efficient for polynomials with many terms.
75
76
77///////////////////////////////////////////////////////////////////////////////
78
[0bc582c]79proc roots(poly f)
80"USAGE:   roots(f); where f is a polynomial
[9173792]81PURPOSE: compute all roots of f in a finite extension of the ground field
[4e461ff]82         without multiplicities.
83RETURN:  ring, a polynomial ring over an extension field of the ground field,
[9173792]84         containing a list 'roots' and polynomials 'newA' and 'f':
85  @format
86  - 'roots' is the list of roots of the polynomial f (no multiplicities)
[34b0314]87  - if the ground field is Q(a') and the extension field is Q(a), then
[3c4dcc]88    'newA' is the representation of a' in Q(a).
[9173792]89    If the basering contains a parameter 'a' and the minpoly remains unchanged
90    then 'newA' = 'a'.
91    If the basering does not contain a parameter then 'newA' = 'a' (default).
92  - 'f' is the polynomial f in Q(a) (a' being substituted by 'newA')
93  @end format
[4e461ff]94ASSUME:  ground field to be Q or a simple extension of Q given by a minpoly
[0bc582c]95EXAMPLE: example  roots; shows an example
[4e461ff]96"
97{
98  int dbPrt = printlevel-voice+3;
99
100  // create a new ring where par(1) is replaced by the variable
101  // with the same name or, if basering does not contain a parameter,
102  // with a new variable 'a'.
103
104  def ROB = basering;
105  def ROR = TransferRing(basering);
106  setring ROR;
[6fe3a0]107  export(ROR);
[4e461ff]108
109  // get the polynomial f and find the roots
110
111  poly f = imap(ROB, f);
[0bc582c]112  list result = rootsMain(f);  // find roots of f
[4e461ff]113
[7d56875]114  // store the roots and the new representation of 'a' and transform
[4e461ff]115  // the coefficients of f.
116
117  list roots = result[1];
118  poly newA = result[2];
119  map F = basering, maxideal(1);
120  F[nvars(basering)] = newA;
121  poly fn = SimplifyPoly(F(f));
122
123  // create a new ring with minploy = mpoly[1] (from ROR)
124
125  def RON = NewBaseRing();
126  setring(RON);
127  list roots = imap(ROR, roots);
128  poly newA = imap(ROR, newA);
129  poly f = imap(ROR, fn);
[3b77465]130  kill ROR;
[4e461ff]131  export(roots);
132  export(newA);
133  export(f); dbprint(dbPrt,"
[0bc582c]134// 'roots' created a new ring which contains the list 'roots' and
[4e461ff]135// the polynomials 'f' and 'newA'
136// To access the roots, newA and the new representation of f, type
[0bc582c]137   def R = roots(f); setring R; roots; newA; f;
[4e461ff]138");
139  return(RON);
140}
141example
142{"EXAMPLE:";  echo = 2;
143  ring R = (0,a), x, lp;
144  minpoly = a2+1;
145  poly f = x3 - a;
[0bc582c]146  def R1 = roots(f);
[4e461ff]147  setring R1;
148  minpoly;
149  newA;
150  f;
151  roots;
152  map F;
153  F[1] = roots[1];
154  F(f);
155}
156
157///////////////////////////////////////////////////////////////////////////////
158
[0bc582c]159proc rootsMain(poly f)
160"USAGE:   rootsMain(f); where f is a polynomial
[9173792]161PURPOSE: compute all roots of f in a finite extension of the ground field
[4e461ff]162         without multiplicities.
163RETURN:  list, all entries are polynomials
[9173792]164  @format
165  _[1] = roots of f, each entry is a polynomial
[0bc582c]166  _[2] = 'newA' - if the ground field is Q(b) and the extension field
167         is Q(a), then 'newA' is the representation of b in Q(a)
[34b0314]168  _[3] = minpoly of the algebraic extension of the ground field
[9173792]169  @end format
170ASSUME:  basering = Q[x,a] ideal mpoly must be defined, it might be 0!
[731e67e]171NOTE:    might change the ideal mpoly!!
[0bc582c]172EXAMPLE: example  roots; shows an example
[4e461ff]173"
174{
175  int i, linFactors, nlinFactors, dbPrt;
176  intvec wt = 1,0;    // deg(a) = 0
177  list factorList, nlFactors, nlMult, roots, result;
178  poly fa, lc;
179
180  dbPrt = printlevel-voice+3;
181
182  // factor f in Q(a)[t] to obtain the roots lying in Q(a)
183  // firstly, find roots of the linear factors,
184  // nonlinear factors are processed later
185
[0bc582c]186  dbprint(dbPrt, "roots of " + string(f) +  ", minimal polynomial = " + string(mpoly[1]));
187  factorList = factorMain(f);          // Factorize f
[4e461ff]188  dbprint(dbPrt, (" prime factors of f are : " + string(factorList[1])));
189
190  linFactors = 0;
191  nlinFactors = 0;
192  for(i = 2; i <= size(factorList[1]); i = i + 1) {  // find linear and nonlinear factors
193    fa = factorList[1][i];
194    if(deg(fa, wt) == 1) {
195      linFactors++;        // get the root from the linear factor
196      lc = LeadTerm(fa, 1)[3];
[0bc582c]197      fa = MultPolys(invertNumberMain(lc), fa); // make factor monic
[4e461ff]198      roots[linFactors] = var(1) - fa;  // fa is monic !!
199    }
200    else {            // ignore nonlinear factors
201      nlinFactors++;
202      nlFactors[nlinFactors] = factorList[1][i];
203      nlMult[nlinFactors] = factorList[2][i];
204    }
205  }
[34b0314]206  if(linFactors == size(factorList[1]) - 1) {    // all roots of f are contained in the ground field
[4e461ff]207    result[1] = roots;
208    result[2] = var(2);
209    result[3] = mpoly[1];
210    return(result);
211  }
212
[34b0314]213  // process the nonlinear factors, i.e., extend the ground field
[4e461ff]214  // where a nonlinear factor (irreducible) is a minimal polynomial
215  // compute the primitive element of this extension
216
217  ideal primElem, minPolys, Fid;
218  list partSol;
219  map F, Xchange;
220  poly f1, newA, mp, oldMinPoly;
221
222  Fid = mpoly;
223  F[1] = var(1);
224  Xchange[1] = var(2);      // the variables have to be exchanged
225  Xchange[2] = var(1);      // for the use of 'primitive'
226
227  if(nlinFactors == 1) {            // one nl factor
228
229    // compute the roots of the nonlinear (irreducible, monic) factor f1 of f
230    // by extending the basefield by a' with minimal polynomial f1
[0bc582c]231    // Then call roots(f1) to find the roots of f1 over the new base field
[4e461ff]232
233    f1 = nlFactors[1];
234    if(mpoly[1] != 0) {
235      mp = mpoly[1];
236      minPolys = Xchange(mp), Xchange(f1);
237      primElem = primitive_extra(minPolys);  // no random coord. change
238      mpoly = std(primElem[1]);
239      F = basering, maxideal(1);
240      F[2] = primElem[2];      // transfer all to the new representation
241      newA = primElem[2];      // new representation of a
242      f1 = SimplifyPoly(F(f1));     //reduce(F(f1), mpoly);
243      if(size(roots) > 0) {roots = SimplifyData(F(roots));}
244    }
245    else {
246      mpoly = std(Xchange(f1));
247      newA = var(2);
248    }
249    result[3] = mpoly[1];
250    oldMinPoly = mpoly[1];
[0bc582c]251    partSol = rootsMain(f1);    // find roots of f1 over extended field
[4e461ff]252
253    if(oldMinPoly != partSol[3]) {    // minpoly has changed ?
254      // all previously computed roots must be transformed
255      // because the minpoly has changed
256      result[3] = partSol[3];    // new minpoly
257      F[2] = partSol[2];    // new representation of algebraic number
258      if(size(roots) > 0) {roots = SimplifyData(F(roots)); }
259      newA = SimplifyPoly(F(newA)); // F(newA);
260    }
261    roots = roots + partSol[1];  // add roots
262    result[2] = newA;
263    result[1] = roots;
264  }
265  else {  // more than one nonlinear (irreducible) factor (f_1,...,f_r)
[0bc582c]266    // solve each of them by rootsMain(f_i), append their roots
[4e461ff]267    // change the minpoly and transform all previously computed
268    // roots if necessary.
269    // Note that the for-loop is more or less book-keeping
270
271    newA = var(2);
272    result[2] = newA;
273    for(i = 1; i <= size(nlFactors); i = i + 1) {
274      oldMinPoly = mpoly[1];
[0bc582c]275      partSol = rootsMain(nlFactors[i]);    // main work
[4e461ff]276      nlFactors[i] = 0;        // delete factor
277      result[3] = partSol[3];        // store minpoly
278
279      // book-keeping starts here as in the case 1 nonlinear factor
280
281      if(oldMinPoly != partSol[3]) { // minpoly has changed
282        F = basering, maxideal(1);
283        F[2] = partSol[2];    // transfer all to the new representation
284        newA = SimplifyPoly(F(newA));    // F(newA); new representation of a
285        result[2] = newA;
286        if(i < size(nlFactors)) {
287          nlFactors = SimplifyData(F(nlFactors));
288        } // transform remaining factors
289        if(size(roots) > 0) {roots = SimplifyData(F(roots));}
290      }
291      roots = roots + partSol[1];    // transform roots
292      result[1] = roots;
293    }  // end more than one nl factor
294
295  }
296  return(result);
297}
298
299///////////////////////////////////////////////////////////////////////////////
300
[0bc582c]301proc zeroSet(ideal I, list #)
302"USAGE:   zeroSet(I [,opt] ); I=ideal, opt=integer
[9173792]303PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension
[34b0314]304         of the ground field.
[4e461ff]305RETURN:  ring, a polynomial ring over an extension field of the ground field,
[9173792]306         containing a list 'zeroset', a polynomial 'newA', and an
307         ideal 'id':
308  @format
309  - 'zeroset' is the list of the zeros of the ideal I, each zero is an ideal.
[0bc582c]310  - if the ground field is Q(b) and the extension field is Q(a), then
311    'newA' is the representation of b in Q(a).
[9173792]312    If the basering contains a parameter 'a' and the minpoly remains unchanged
313    then 'newA' = 'a'.
[3c4dcc]314    If the basering does not contain a parameter then 'newA' = 'a' (default).
[9173792]315  - 'id' is the ideal I in Q(a)[x_1,...] (a' substituted by 'newA')
316  @end format
[d12655]317ASSUME:  dim(I) = 0, and ground field to be Q or a simple extension of Q given
318         by a minpoly.
[0bc582c]319OPTIONS: opt = 0: no primary decomposition (default)
320         opt > 0: primary decomposition
321NOTE:    If I contains an algebraic number (parameter) then I must be
[35f23d]322         transformed w.r.t. 'newA' in the new ring.
[0bc582c]323EXAMPLE: example zeroSet; shows an example
[4e461ff]324"
325{
326  int primaryDecQ, dbPrt;
327  list rp;
328
329  dbPrt = printlevel-voice+2;
330
331  if(size(#) > 0) { primaryDecQ = #[1]; }
332  else { primaryDecQ = 0; }
333
[3c4dcc]334  // create a new ring 'ZSR' with one additional variable instead of the
[6fe3a0]335  // parameter
[3c4dcc]336  // if the basering does not contain a parameter then 'a' is used as the
[6fe3a0]337  // additional variable.
[4e461ff]338
339  def RZSB = basering;
[6fe3a0]340  def ZSR = TransferRing(RZSB);
[4e461ff]341  setring ZSR;
342
343  // get ideal I and find the zero-set
344
345  ideal id = std(imap(RZSB, I));
[6fe3a0]346//  print(dim(id));
347  if(dim(id) > 1) {       // new variable adjoined to ZSR
348    ERROR(" ideal not zerodimensional ");
349  }
[4e461ff]350
[0bc582c]351  list result = zeroSetMain(id, primaryDecQ);
[4e461ff]352
353  // store the zero-set, minimal polynomial and the new representative of 'a'
354
355  list zeroset = result[1];
356  poly newA = result[2];
357  poly minPoly = result[3][1];
358
[3c4dcc]359  // transform the generators of the ideal I w.r.t. the new representation
[6fe3a0]360  // of 'a'
[4e461ff]361
362  map F = basering, maxideal(1);
363  F[nvars(basering)] = newA;
364  id = SimplifyData(F(id));
365
366  // create a new ring with minpoly = minPoly
367
368  def RZBN = NewBaseRing();
369  setring RZBN;
370
371  list zeroset = imap(ZSR, zeroset);
372  poly newA = imap(ZSR, newA);
373  ideal id = imap(ZSR, id);
[3b77465]374  kill ZSR;
[4e461ff]375
376  export(id);
377  export(zeroset);
378  export(newA);
379    dbprint(dbPrt,"
[0bc582c]380// 'zeroSet' created a new ring which contains the list 'zeroset', the ideal
[4e461ff]381// 'id' and the polynomial 'newA'. 'id' is the ideal of the input transformed
382// w.r.t. 'newA'.
383// To access the zero-set, 'newA' and the new representation of the ideal, type
[0bc582c]384   def R = zeroSet(I); setring R; zeroset; newA; id;
[4e461ff]385");
[6fe3a0]386  setring RZSB;
[4e461ff]387  return(RZBN);
388}
389example
390{"EXAMPLE:";  echo = 2;
391  ring R = (0,a), (x,y,z), lp;
392  minpoly = a2 + 1;
393  ideal I = x2 - 1/2, a*z - 1, y - 2;
[0bc582c]394  def T = zeroSet(I);
[4e461ff]395  setring T;
396  minpoly;
397  newA;
398  id;
399  zeroset;
400  map F1 = basering, zeroset[1];
401  map F2 = basering, zeroset[2];
402  F1(id);
403  F2(id);
404}
405
406///////////////////////////////////////////////////////////////////////////////
407
[0bc582c]408proc invertNumberMain(poly f)
409"USAGE:   invertNumberMain(f); where f is a polynomial
[731e67e]410PURPOSE: compute 1/f if f is a number in Q(a), i.e., f is represented by a
[4e461ff]411         polynomial in Q[a].
412RETURN:  poly 1/f
[9173792]413ASSUME:  basering = Q[x_1,...,x_n,a], ideal mpoly must be defined and != 0 !
[980120f]414NOTE:    outdated, use / instead
[4e461ff]415"
416{
417  if(diff(f, var(1)) != 0) { ERROR("number must not contain variable !");}
418
419  int n = nvars(basering);
420  def RINB = basering;
421  string ringSTR = "ring RINR = 0, " + string(var(n)) + ", dp;";
422  execute(ringSTR);        // new ring = Q[a]
423
424  list gcdList;
425  poly f, g, inv;
426
427  f = imap(RINB, f);
428  g = imap(RINB, mpoly)[1];
429
430  if(diff(f, var(1)) != 0) { inv = extgcd(f, g)[2]; }  // f contains var(1)
431  else {  inv = 1/f;}          // f element in Q
432
433  setring(RINB);
434  return(imap(RINR, inv));
435}
436
437///////////////////////////////////////////////////////////////////////////////
438
439proc MultPolys(poly f, poly g)
440"USAGE:   MultPolys(f, g); poly f,g
441PURPOSE: multiply the polynomials f and g and reduce them w.r.t. mpoly
442RETURN:  poly f*g
443ASSUME:  basering = Q[x,a], ideal mpoly must be defined, it might be 0 !
444"
445{
446  return(SimplifyPoly(f * g));
447}
448
449///////////////////////////////////////////////////////////////////////////////
450
451proc LeadTerm(poly f, int i)
452"USAGE:   LeadTerm(f); poly f, int i
[9173792]453PURPOSE: compute the leading coef and term of f w.r.t var(i), where the last
[4e461ff]454         ring variable is treated as a parameter.
455RETURN:  list of polynomials
456         _[1] = leading term
457         _[2] = leading monomial
458         _[3] = leading coefficient
459ASSUME:  basering = Q[x_1,...,x_n,a]
460"
461{
462  list result;
463  matrix co = coef(f, var(i));
464  result[1] = co[1, 1]*co[2, 1];
465  result[2] = co[1, 1];
466  result[3] = co[2, 1];
467  return(result);
468}
469
470///////////////////////////////////////////////////////////////////////////////
471
[c335c5]472proc Quotient(poly f, poly g)
473"USAGE:   Quotient(f, g); where f,g are polynomials;
[6fe3a0]474PURPOSE: compute the quotient q and remainder r s.t. f = g*q + r, deg(r) < deg(g)
[4e461ff]475RETURN:  list of polynomials
[6fe3a0]476  @format
477  _[1] = quotient  q
478  _[2] = remainder r
479  @end format
[4e461ff]480ASSUME:  basering = Q[x] or Q(a)[x]
[980120f]481NOTE: outdated, use div/mod instead
[c335c5]482EXAMPLE: example  Quotient; shows an example
[4e461ff]483"
484{
[6fe3a0]485  def QUOB = basering;
486  def QUOR = TransferRing(basering);  // new ring with parameter 'a' replaced by a variable
487  setring QUOR;
488  export(QUOR);
489  poly f = imap(QUOB, f);
490  poly g = imap(QUOB, g);
[0bc582c]491  list result = quotientMain(f, g);
[6fe3a0]492
493  setring(QUOB);
494  list result = imap(QUOR, result);
[3b77465]495  kill QUOR;
[6fe3a0]496  return(result);
[4e461ff]497}
498example
499{"EXAMPLE:";  echo = 2;
500 ring R = (0,a), x, lp;
501 minpoly = a2+1;
502 poly f =  x4 - 2;
503 poly g = x - a;
[c335c5]504 list qr = Quotient(f, g);
[4e461ff]505 qr;
506 qr[1]*g + qr[2] - f;
507}
508
[0bc582c]509proc quotientMain(poly f, poly g)
510"USAGE:   quotientMain(f, g); where f,g are polynomials
[731e67e]511PURPOSE: compute the quotient q and remainder r s.th. f = g*q + r, deg(r) < deg(g)
[4e461ff]512RETURN:  list of polynomials
[6fe3a0]513  @format
514  _[1] = quotient  q
515  _[2] = remainder r
516  @end format
517ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
518         this represents the ring Q(a)[x] together with its minimal polynomial.
[980120f]519NOTE: outdated, use div/mod instead
[4e461ff]520"
521{
[6fe3a0]522  if(g == 0) { ERROR("Division by zero !");}
523
524  def QMB = basering;
525  def QMR = NewBaseRing();
526  setring QMR;
527  poly f, g, h;
528  h = imap(QMB, f) / imap(QMB, g);
529  setring QMB;
530  return(list(imap(QMR, h), 0));
[4e461ff]531}
532
533///////////////////////////////////////////////////////////////////////////////
534
[0bc582c]535proc remainder(poly f, poly g)
536"USAGE:   remainder(f, g); where f,g are polynomials
[9173792]537PURPOSE: compute the remainder of the division of f by g, i.e. a polynomial r
538         s.t. f = g*q + r, deg(r) < deg(g).
[4e461ff]539RETURN:  poly
540ASSUME:  basering = Q[x] or Q(a)[x]
[980120f]541NOTE: outdated, use mod/reduce instead
[4e461ff]542"
543{
544  def REMB = basering;
545  def REMR = TransferRing(basering);  // new ring with parameter 'a' replaced by a variable
546  setring(REMR);
[6fe3a0]547  export(REMR);
[4e461ff]548  poly f = imap(REMB, f);
549  poly g = imap(REMB, g);
[0bc582c]550  poly h = remainderMain(f, g);
[4e461ff]551
552  setring(REMB);
553  poly r = imap(REMR, h);
[3b77465]554  kill REMR;
[4e461ff]555  return(r);
556}
557example
558{"EXAMPLE:";  echo = 2;
559 ring R = (0,a), x, lp;
560 minpoly = a2+1;
561 poly f =  x4 - 1;
562 poly g = x3 - 1;
[0bc582c]563 remainder(f, g);
[4e461ff]564}
565
[0bc582c]566proc remainderMain(poly f, poly g)
567"USAGE:   remainderMain(f, g); where f,g are polynomials
[9173792]568PURPOSE: compute the remainder r s.t. f = g*q + r, deg(r) < deg(g)
[4e461ff]569RETURN:  poly
[9173792]570ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
571         this represents the ring Q(a)[x] together with its minimal polynomial.
[980120f]572NOTE: outdated, use mod/reduce instead
[4e461ff]573"
574{
575  int dg;
576  intvec wt = 1,0;;
577  poly lc, g1, r;
578
579  if(deg(g, wt) == 0) { return(0); }
580
581  lc = LeadTerm(g, 1)[3];
[0bc582c]582  g1 = MultPolys(invertNumberMain(lc), g);  // make g monic
[4e461ff]583
584  return(SimplifyPoly(reduce(f, std(g1))));
585}
586
587///////////////////////////////////////////////////////////////////////////////
588
[0bc582c]589proc egcdMain(poly f, poly g)
590"USAGE:   egcdMain(f, g); where f,g are polynomials
[9173792]591PURPOSE: compute the polynomial gcd of f and g over Q(a)[x]
[4e461ff]592RETURN:  poly
[9173792]593ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
594         this represents the ring Q(a)[x] together with its minimal polynomial.
[980120f]595NOTE: outdated, use gcd instead
[4e461ff]596EXAMPLE: example EGCD; shows an example
597"
598{
[c1986a]599// might be extended to return s1, s2 s.t. f*s1 + g*s2 = gcd
[4e461ff]600  int i = 1;
601  poly r1, r2, r;
602
603  r1 = f;
604  r2 = g;
605
606  while(r2 != 0) {
[0bc582c]607    r  = remainderMain(r1, r2);
[4e461ff]608    r1 = r2;
609    r2 = r;
610  }
611  return(r1);
612}
613
614///////////////////////////////////////////////////////////////////////////////
615
616proc MEGCD(poly f, poly g, int varIndex)
617"USAGE:   MEGCD(f, g, i); poly f, g; int i
[9173792]618PURPOSE: compute  the polynomial gcd of f and g in the i'th variable
[4e461ff]619RETURN:  poly
[d12655]620ASSUME:  f, g are polynomials in var(i), last variable is the algebraic number
[4e461ff]621EXAMPLE: example  MEGCD; shows an example
622"
623// might be extended to return s1, s2 s.t. f*s1 + g*s2 = gc
624// not used !
625{
626  string @str, @sf, @sg, @mp, @parName;
627
628  def @RGCDB = basering;
629
630  @sf = string(f);
631  @sg = string(g);
632  @mp = string(minpoly);
633
634  if(npars(basering) == 0) { @parName = "0";}
635  else { @parName = "(0, " + parstr(basering) + ")"; }
636  @str = "ring @RGCD = " + @parName + ", " + string(var(varIndex)) + ", dp;";
637  execute(@str);
638  if(@mp != "0") { execute ("minpoly = " + @mp + ";"); }
639  execute("poly @f = " + @sf + ";");
640  execute("poly @g = " + @sg + ";");
[6fe3a0]641  export(@RGCD);
[4f5b07]642  poly @h = gcd(@f, @g);
[4e461ff]643  setring(@RGCDB);
644  poly h = imap(@RGCD, @h);
[3b77465]645  kill @RGCD;
[4e461ff]646  return(h);
647}
648
649///////////////////////////////////////////////////////////////////////////////
650
[0bc582c]651proc sqfrNorm(poly f)
652"USAGE:   sqfrNorm(f); where f is a polynomial
[9173792]653PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x].
654RETURN:  list with 3 entries
655  @format
656  _[1] = squarefree norm of g (poly)
657  _[2] = g (= f(x - s*a)) (poly)
658  _[3] = s (int)
659  @end format
[4e461ff]660ASSUME:  f must be squarefree, basering = Q(a)[x] and minpoly != 0.
661NOTE:    the norm is an element of Q[x]
[0bc582c]662EXAMPLE: example  sqfrNorm; shows an example
[4e461ff]663"
664{
665  def SNB = basering;
[3c4dcc]666  def SNR = TransferRing(SNB);  // new ring with parameter 'a'
[6fe3a0]667                                // replaced by a variable
[4e461ff]668  setring SNR;
669  poly f = imap(SNB, f);
[0bc582c]670  list result = sqfrNormMain(f);  // squarefree norm of f
[4e461ff]671
[6fe3a0]672  setring SNB;
[4e461ff]673  list result = imap(SNR, result);
[6fe3a0]674  kill SNR;
[4e461ff]675  return(result);
676}
677example
678{"EXAMPLE:";  echo = 2;
679   ring R = (0,a), x, lp;
680   minpoly = a2+1;
681  poly f =  x4 - 2*x + 1;
[0bc582c]682  sqfrNorm(f);
[4e461ff]683}
684
[0bc582c]685proc sqfrNormMain(poly f)
686"USAGE:   sqfrNorm(f); where f is a polynomial
[9173792]687PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x].
688RETURN:  list with 3 entries
689  @format
690  _[1] = squarefree norm of g (poly)
691  _[2] = g (= f(x - s*a)) (poly)
692  _[3] = s (int)
693  @end format
694ASSUME:  f must be squarefree, basering = Q[x,a] and ideal mpoly is equal to
[731e67e]695         'minpoly', this represents the ring Q(a)[x] together with 'minpoly'.
[4e461ff]696NOTE:   the norm is an element of Q[x]
697EXAMPLE: example  SqfrNorm; shows an example
698"
699{
[6fe3a0]700  def SNRMB = basering;
[4e461ff]701  int s = 0;
702  intvec wt = 1,0;
703  ideal mapId;
704  // list result;
705  poly g, N, N1, h;
706  string ringSTR;
707
708  mapId[1] = var(1) - var(2);    // linear transformation
709  mapId[2] = var(2);
[6fe3a0]710  map Fs = SNRMB, mapId;
[4e461ff]711
712  N = resultant(f, mpoly[1], var(2));  // norm of f
713  N1 = diff(N, var(1));
714  g = f;
715
716  ringSTR = "ring SNRM1 = 0, " + string(var(1)) + ", dp;";  // univariate ring
717  execute(ringSTR);
718  poly N, N1, h;        // N, N1 do not contain 'a', use built-in gcd
719  h = gcd(imap(SNRMB, N), imap(SNRMB, N1));
720  setring(SNRMB);
721  h = imap(SNRM1, h);
722  while(deg(h, wt) != 0) {    // while norm is not squarefree
723    s = s + 1;
724    g = reduce(Fs(g), mpoly);
725    N = reduce(resultant(g, mpoly[1], var(2)), mpoly);  // norm of g
726    N1 = reduce(diff(N, var(1)), mpoly);
727    setring(SNRM1);
728    h = gcd(imap(SNRMB, N), imap(SNRMB, N1));
729    setring(SNRMB);
730    h = imap(SNRM1, h);
731  }
732  return(list(N, g, s));
733}
734
735///////////////////////////////////////////////////////////////////////////////
736
[0bc582c]737proc factorMain(poly f)
738"USAGE:   factorMain(f); where f is a polynomial
[9173792]739PURPOSE: compute the factorization of the squarefree poly f over Q(a)[t],
[d12655]740         minpoly  = p(a).
[9173792]741RETURN:  list with 2 entries
742  @format
743  _[1] = factors, first is a constant
744  _[2] = multiplicities (not yet implemented)
745  @end format
746ASSUME:  basering = Q[x,a], representing Q(a)[x]. An ideal mpoly must
747         be defined, representing the minimal polynomial (it might be 0!).
[980120f]748NOTE: outdated, use factorize instead
[4e461ff]749EXAMPLE: example  Factor; shows an example
750"
[c1986a]751{
[4e461ff]752// extend this by a squarefree factorization !!
753// multiplicities are not valid !!
754  int i, s;
755  list normList, factorList, quo_rem;
756  poly f1, h, h1, H, g, leadCoef, invCoeff;
757  ideal fac1, fac2;
758  map F;
759
760  // if no minimal polynomial is defined then use 'factorize'
761  // FactorOverQ is wrapped around 'factorize'
762
763  if(mpoly[1] == 0) {
764    // print(" factorize : deg = " + string(deg(f, intvec(1,0))));
765    factorList = factorize(f); // FactorOverQ(f);
766    return(factorList);
767  }
768
769  // if mpoly != 0 and f does not contain the algebraic number, a root of
770  // f might be contained in Q(a). Hence one must not use 'factorize'.
771
772  fac1[1] = 1;
773  fac2[1] = 1;
[0bc582c]774  normList = sqfrNormMain(f);
[4e461ff]775  // print(" factorize : deg = " + string(deg(normList[1], intvec(1,0))));
776  factorList = factorize(normList[1]);     // factor squarefree norm of f over Q[x]
777  g = normList[2];
778  s = normList[3];
779  F[1] = var(1) + s*var(2);      // inverse transformation
780  F[2] = var(2);
781  fac1[1] = factorList[1][1];
782  fac2[1] = factorList[2][1];
783  for(i = 2; i <= size(factorList[1]); i = i + 1) {
784    H = factorList[1][i];
[0bc582c]785    h = egcdMain(H, g);
786    quo_rem = quotientMain(g, h);
[4e461ff]787    g = quo_rem[1];
788    fac1[i] = SimplifyPoly(F(h));
789    fac2[i] = 1;        // to be changed later
790  }
791  return(list(fac1, fac2));
792}
793
794///////////////////////////////////////////////////////////////////////////////
795
[0bc582c]796proc zeroSetMain(ideal I, int primDecQ)
797"USAGE:   zeroSetMain(ideal I, int opt); ideal I, int opt
[9173792]798PURPOSE: compute the zero-set of the zero-dim. ideal I, in a simple extension
[34b0314]799         of the ground field.
[4e461ff]800RETURN:  list
[d12655]801         - 'f' is the polynomial f in  Q(a) (a' being substituted by newA)
[4e461ff]802         _[1] = zero-set (list), is the list of the zero-set of the ideal I,
803                each entry is an ideal.
[34b0314]804         _[2] = 'newA';  if the ground field is Q(a') and the extension field
[4e461ff]805                is Q(a), then 'newA' is the representation of a' in Q(a).
806                If the basering contains a parameter 'a' and the minpoly
807                remains unchanged then 'newA' = 'a'. If the basering does not
808                contain a parameter then 'newA' = 'a' (default).
[d12655]809         _[3] = 'mpoly' (ideal), the minimal polynomial of the simple extension
810                of the ground field.
811ASSUME:  basering = K[x_1,x_2,...,x_n] where K = Q or a simple extension of Q
812         given by a minpoly; dim(I) = 0.
[4e461ff]813NOTE:    opt = 0  no primary decomposition
[d12655]814         opt > 0  use a primary decomposition
[0bc582c]815EXAMPLE: example zeroSet; shows an example
[4e461ff]816"
817{
[0bc582c]818  // main work is done in zeroSetMainWork, here the zero-set of each ideal from the
819  // primary decompostion is coputed by menas of zeroSetMainWork, and then the
[4e461ff]820  // minpoly and the parameter representing the algebraic extension are
821  // transformed according to 'newA', i.e., only bookeeping is done.
822
[6fe3a0]823  def altring=basering;
[4e461ff]824  int i, j, n, noMP, dbPrt;
825  intvec w;
826  list currentSol, result, idealList, primDecList, zeroSet;
827  ideal J;
828  map Fa;
829  poly newA, oldMinPoly;
830
831  dbPrt = printlevel-voice+2;
[0bc582c]832  dbprint(dbPrt, "zeroSet of " + string(I) + ", minpoly = " + string(minpoly));
[4e461ff]833
834  n = nvars(basering) - 1;
835  for(i = 1; i <= n; i++) { w[i] = 1;}
836  w[n + 1] = 0;
837
[0bc582c]838  if(primDecQ == 0) { return(zeroSetMainWork(I, w, 0)); }
[4e461ff]839
840  newA = var(n + 1);
841  if(mpoly[1] == 0) { noMP = 1;}
842  else {noMP = 0;}
843
844  primDecList = primdecGTZ(I);      // primary decomposition
845  dbprint(dbPrt, "primary decomposition consists of " + string(size(primDecList)) + " primary ideals ");
846  // idealList = PDSort(idealList);    // high degrees first
847
848  for(i = 1; i <= size(primDecList); i = i + 1) {
849    idealList[i] = primDecList[i][2];  // use prime component
850    dbprint(dbPrt, string(i) + "  " + string(idealList[i]));
851  }
852
853  // compute the zero-set of each primary ideal and join them.
[34b0314]854  // If necessary, change the ground field and transform the zero-set
[4e461ff]855
856  dbprint(dbPrt, "
857find the zero-set of each primary ideal, form the union
858and keep track of the minimal polynomials ");
859
860  for(i = 1; i <= size(idealList); i = i + 1) {
861    J = idealList[i];
862    idealList[i] = 0;
863    oldMinPoly = mpoly[1];
864    dbprint(dbPrt, " ideal#" + string(i) + " of " + string(size(idealList)) + " = " + string(J));
[0bc582c]865    currentSol = zeroSetMainWork(J, w, 0);
[4e461ff]866
867    if(oldMinPoly != currentSol[3]) {   // change minpoly and transform solutions
868      dbprint(dbPrt, " change minpoly to " + string(currentSol[3][1]));
869      dbprint(dbPrt, " new representation of algebraic number = " + string(currentSol[2]));
870      if(!noMP) {      // transform the algebraic number a
871        Fa = basering, maxideal(1);
872        Fa[n + 1] = currentSol[2];
873        newA = SimplifyPoly(Fa(newA));  // new representation of a
874        if(size(zeroSet) > 0) {zeroSet = SimplifyZeroset(Fa(zeroSet)); }
875        if(i < size(idealList)) { idealList = SimplifyZeroset(Fa(idealList)); }
876      }
877      else { noMP = 0;}
878    }
879    zeroSet = zeroSet + currentSol[1];    // add new elements
880  }
881  return(list(zeroSet, newA, mpoly));
882}
883
884///////////////////////////////////////////////////////////////////////////////
885
[0bc582c]886proc zeroSetMainWork(ideal id, intvec wt, int sVars)
887"USAGE:   zeroSetMainWork(I, wt, sVars);
[9173792]888PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension
[34b0314]889         of the ground field (without multiplicities).
[4e461ff]890RETURN:  list, all entries are polynomials
891         _[1] = zeros, each entry is an ideal
[34b0314]892         _[2] = newA; if the ground field is Q(a') this is the rep. of a' w.r.t. a
893         _[3] = minpoly of the algebraic extension of the ground field (ideal)
[4e461ff]894         _[4] = name of algebraic number (default = 'a')
895ASSUME:  basering = Q[x_1,x_2,...,x_n,a]
[9173792]896         ideal mpoly must be defined, it might be 0!
[4e461ff]897NOTE:    might change 'mpoly' !!
898EXAMPLE: example  IdealSolve; shows an example
899"
900{
[6fe3a0]901  def altring=basering;
[4e461ff]902  int i, j, k, nrSols, n, noMP;
903  ideal I, generators, gens, solid, partsolid;
904  list linSol, linearSolution, nLinSol, nonlinSolutions, partSol, sol, solutions, result;
905  list linIndex, nlinIndex, index;
906  map Fa, Fsubs;
907  poly oldMinPoly, newA;
908
909  if(mpoly[1] == 0) { noMP = 1;}
910  else { noMP = 0;}
911  n = nvars(basering) - 1;
912  newA = var(n + 1);
913
914  I = std(id);
915
916  // find linear solutions of univariate generators
917
918  linSol = LinearZeroSetMain(I, wt);
919  generators = linSol[3];      // they are a standardbasis
920  linIndex = linSol[2];
921  linearSolution = linSol[1];
922  if(size(linIndex) + sVars == n) {    // all variables solved
923    solid = SubsMapIdeal(linearSolution, linIndex, 0);
924    result[1] = list(solid);
925    result[2] = var(n + 1);
926    result[3] = mpoly;
927    return(result);
928  }
929
930  // find roots of the nonlinear univariate polynomials of generators
931  // if necessary, transform linear solutions w.r.t. newA
932
933  oldMinPoly = mpoly[1];
934  nLinSol =  NonLinearZeroSetMain(generators, wt);    // find solutions of univariate generators
935  nonlinSolutions = nLinSol[1];    // store solutions
936  nlinIndex = nLinSol[4];     // and index of solved variables
937  generators = nLinSol[5];    // new generators
938
939  // change minpoly if necessary and transform the ideal and the partial solutions
940
941  if(oldMinPoly != nLinSol[3]) {
942    newA = nLinSol[2];
943    if(!noMP && size(linearSolution) > 0) {    // transform the algebraic number a
944      Fa = basering, maxideal(1);
945      Fa[n + 1] = newA;
946      linearSolution = SimplifyData(Fa(linearSolution));  // ...
947    }
948  }
949
950  // check if all variables are solved.
951
952  if(size(linIndex) + size(nlinIndex) == n - sVars) {
953    solutions = MergeSolutions(linearSolution, linIndex, nonlinSolutions, nlinIndex, list(), n);
954  }
955
956  else {
957
958  // some variables are not solved.
959  // substitute each partial solution in generators and find the
960  // zero set of the resulting ideal by recursive application
[0bc582c]961  // of zeroSetMainWork !
[4e461ff]962
963  index = linIndex + nlinIndex;
964  nrSols = 0;
965  for(i = 1; i <=  size(nonlinSolutions); i = i + 1) {
966    sol = linearSolution + nonlinSolutions[i];
967    solid = SubsMapIdeal(sol, index, 1);
968    Fsubs = basering, solid;
969    gens = std(SimplifyData(Fsubs(generators)));    // substitute partial solution
970    oldMinPoly = mpoly[1];
[0bc582c]971    partSol = zeroSetMainWork(gens, wt, size(index) + sVars);
[4e461ff]972
973    if(oldMinPoly != partSol[3]) {    // minpoly has changed
974      Fa = basering, maxideal(1);
975      Fa[n + 1] = partSol[2];    // a -> p(a), representation of a w.r.t. new minpoly
976      newA = reduce(Fa(newA), mpoly);
977      generators = std(SimplifyData(Fa(generators)));
978      if(size(linearSolution) > 0) { linearSolution = SimplifyData(Fa(linearSolution));}
979      if(size(nonlinSolutions) > 0) {
980        nonlinSolutions = SimplifyZeroset(Fa(nonlinSolutions));
981      }
982      sol = linearSolution + nonlinSolutions[i];
983    }
984
985    for(j = 1; j <= size(partSol[1]); j++) {   // for all partial solutions
986      partsolid = partSol[1][j];
987      for(k = 1; k <= size(index); k++) {
988        partsolid[index[k]] = sol[k];
989       }
990      nrSols++;
991      solutions[nrSols] = partsolid;
992    }
993  }
994
995  }  // end else
996  return(list(solutions, newA, mpoly));
997}
998
999///////////////////////////////////////////////////////////////////////////////
1000
1001proc LinearZeroSetMain(ideal I, intvec wt)
1002"USAGE:   LinearZeroSetMain(I, wt)
1003PURPOSE: solve the univariate linear polys in I
1004ASSUME:  basering = Q[x_1,...,x_n,a]
1005RETURN:  list
1006         _[1] = partial solution of I
1007         _[2] = index of solved vars
1008         _[3] = new generators (standardbasis)
1009"
1010{
[6fe3a0]1011  def altring=basering;
[4e461ff]1012  int i, ok, n, found, nrSols;
1013  ideal generators, newGens;
1014  list result, index, totalIndex, vars, sol, temp;
1015  map F;
1016  poly f;
1017
1018  result[1] = index;      // sol[1] should be the empty list
1019  n = nvars(basering) - 1;
1020  generators = I;        // might be wrong, use index !
1021  ok = 1;
1022  nrSols = 0;
1023  while(ok) {
1024    found = 0;
1025    for(i = 1; i <= size(generators); i = i + 1) {
1026      f = generators[i];
1027      vars = Variables(f, n);
1028      if(size(vars) == 1 && deg(f, wt) == 1) {  // univariate,linear
1029        nrSols++; found++;
1030        index[nrSols] = vars[1];
[0bc582c]1031        sol[nrSols] = var(vars[1]) - MultPolys(invertNumberMain(LeadTerm(f, vars[1])[3]), f);
[4e461ff]1032      }
1033    }
1034    if(found > 0) {
1035      F = basering, SubsMapIdeal(sol, index, 1);
1036      newGens = std(SimplifyData(F(generators)));    // substitute, simplify alg. number
1037      if(size(newGens) == 0) {ok = 0;}
1038      generators = newGens;
1039    }
1040    else {
1041      ok = 0;
1042    }
1043  }
1044  if(nrSols > 0) { result[1] = sol;}
1045  result[2] = index;
1046  result[3] = generators;
1047  return(result);
1048}
1049
1050///////////////////////////////////////////////////////////////////////////////
1051
1052proc NonLinearZeroSetMain(ideal I, intvec wt)
[0bc582c]1053"USAGE:   NonLinearZeroSetMain(I, wt);
[9173792]1054PURPOSE: solves the (nonlinear) univariate polynomials in I
[34b0314]1055         of the ground field (without multiplicities).
[4e461ff]1056RETURN:  list, all entries are polynomials
1057         _[1] = list of solutions
1058         _[2] = newA
1059         _[3] = minpoly
1060         _[4] - index of solved variables
1061         _[5] = new representation of I
1062ASSUME:  basering = Q[x_1,x_2,...,x_n,a], ideal 'mpoly' must be defined,
1063         it might be 0 !
1064NOTE:    might change 'mpoly' !!
1065"
1066{
1067  int i, nrSols, ok, n;
1068  ideal generators;
1069  list result, sols, index, vars, partSol;
1070  map F;
1071  poly f, newA;
1072  string ringSTR;
1073
1074  def NLZR = basering;
[6fe3a0]1075  export(NLZR);
[4e461ff]1076
1077  n = nvars(basering) - 1;
1078
1079  generators = I;
1080  newA = var(n + 1);
1081  result[2] = newA;            // default
1082  nrSols = 0;
1083  ok = 1;
1084  i = 1;
1085  while(ok) {
1086
1087    // test if the i-th generator of I is univariate
1088
1089    f = generators[i];
1090    vars = Variables(f, n);
1091    if(size(vars) == 1) {
1092      generators[i] = 0;
1093      generators = simplify(generators, 2);    // remove 0
1094      nrSols++;
1095      index[nrSols] = vars[1];      // store index of solved variable
1096
1097      // create univariate ring
1098
1099      ringSTR = "ring RIS1 = 0, (" + string(var(vars[1])) + ", " + string(var(n+1)) + "), lp;";
1100      execute(ringSTR);
1101      ideal mpoly = std(imap(NLZR, mpoly));
1102      list roots;
1103      poly f = imap(NLZR, f);
[6fe3a0]1104      export(RIS1);
[4e461ff]1105      export(mpoly);
[0bc582c]1106      roots = rootsMain(f);
[6fe3a0]1107
[4e461ff]1108      // get "old" basering with new minpoly
1109
1110      setring(NLZR);
1111      partSol = imap(RIS1, roots);
[3b77465]1112      kill RIS1;
[4e461ff]1113      if(mpoly[1] != partSol[3]) {      // change minpoly
1114        mpoly = std(partSol[3]);
1115        F = NLZR, maxideal(1);
1116        F[n + 1] = partSol[2];
1117        if(size(sols) > 0) {sols = SimplifyZeroset(F(sols)); }
1118        newA = reduce(F(newA), mpoly);    // normal form
1119        result[2] = newA;
1120        generators = SimplifyData(F(generators));  // does not remove 0's
1121      }
1122      sols = ExtendSolutions(sols, partSol[1]);
1123    } // end univariate
1124    else {
1125      i = i + 1;
1126    }
1127    if(i > size(generators)) { ok = 0;}
1128  }
1129  result[1] = sols;
1130  result[3] = mpoly;
1131  result[4] = index;
1132  result[5] = std(generators);
1133
[3b77465]1134  kill NLZR;
[4e461ff]1135  return(result);
1136}
1137
1138///////////////////////////////////////////////////////////////////////////////
1139
1140static proc ExtendSolutions(list solutions, list newSolutions)
1141"USAGE:   ExtendSolutions(sols, newSols); list sols, newSols;
[9173792]1142PURPOSE: extend the entries of 'sols' by the entries of 'newSols',
[4e461ff]1143         each entry of 'newSols' is a number.
1144RETURN:  list
1145ASSUME:  basering = Q[x_1,...,x_n,a], ideal 'mpoly' must be defined,
1146         it might be 0 !
1147NOTE:    used by 'NonLinearZeroSetMain'
1148"
1149{
1150  int i, j, k, n, nrSols;
1151  list newSols, temp;
1152
1153  nrSols = size(solutions);
1154  if(nrSols > 0) {n = size(solutions[1]);}
1155  else {
1156    n = 0;
1157    nrSols = 1;
1158  }
1159  k = 0;
1160  for(i = 1; i <= nrSols; i++) {
1161    for(j = 1; j <= size(newSolutions); j++) {
1162      k++;
1163      if(n == 0) { temp[1] = newSolutions[j];}
1164      else {
1165        temp = solutions[i];
1166        temp[n + 1] = newSolutions[j];
1167      }
1168      newSols[k] = temp;
1169    }
1170  }
1171  return(newSols);
1172}
1173
1174///////////////////////////////////////////////////////////////////////////////
1175
1176static proc MergeSolutions(list sol1, list index1, list sol2, list index2)
1177"USAGE:   MergeSolutions(sol1, index1, sol2, index2); all parameters are lists
1178RETURN:  list
1179PURPOSE: create a list of solutions of size n, each entry of 'sol2' must
[d12655]1180         have size n. 'sol1' is one partial solution (from 'LinearZeroSetMain')
1181         'sol2' is a list of partial solutions (from 'NonLinearZeroSetMain')
[4e461ff]1182ASSUME:  'sol2' is not empty
[0bc582c]1183NOTE:    used by 'zeroSetMainWork'
[4e461ff]1184{
1185  int i, j, k, m;
1186  ideal sol;
1187  list newSols;
1188
1189  m = 0;
1190  for(i = 1; i <= size(sol2); i++) {
1191    m++;
1192    newSols[m] = SubsMapIdeal(sol1 + sol2[i], index1 + index2, 0);
1193  }
1194  return(newSols);
1195}
1196
1197///////////////////////////////////////////////////////////////////////////////
1198
1199static proc SubsMapIdeal(list sol, list index, int opt)
1200"USAGE:   SubsMapIdeal(sol,index,opt); list sol, index; int opt;
[9173792]1201PURPOSE: built an ideal I as follows.
[4e461ff]1202         if i is contained in 'index' then set I[i] = sol[i]
1203         if i is not contained in 'index' then
1204         - opt = 0: set I[i] = 0
1205         - opt = 1: set I[i] = var(i)
1206         if opt = 1 and n = nvars(basering) then set I[n] = var(n).
1207RETURN:  ideal
1208ASSUME:  size(sol) = size(index) <= nvars(basering)
1209"
1210{
1211  int k = 0;
1212  ideal I;
1213  for(int i = 1; i <= nvars(basering) - 1; i = i + 1) {    // built subs. map
[0bc582c]1214    if(containedQ(index, i)) {
[4e461ff]1215      k++;
1216      I[index[k]] = sol[k];
1217    }
1218    else {
1219      if(opt) { I[i] = var(i); }
1220      else { I[i] = 0; }
1221    }
1222  }
1223  if(opt) {I[nvars(basering)] = var(nvars(basering));}
1224  return(I);
1225}
1226
1227///////////////////////////////////////////////////////////////////////////////
1228
1229proc SimplifyZeroset(data)
1230"USAGE:   SimplifyZeroset(data); list data
[9173792]1231PURPOSE: reduce the entries of the elements of 'data' w.r.t. the ideal 'mpoly'
[4e461ff]1232         'data' is a list of ideals/lists.
1233RETURN:  list
1234ASSUME:  basering = Q[x_1,...,x_n,a], order = lp
1235         'data' is a list of ideals
1236         ideal 'mpoly' must be defined, it might be 0 !
1237"
1238{
1239  int i;
1240  list result;
1241
1242  for(i = 1; i <= size(data); i++) {
1243    result[i] = SimplifyData(data[i]);
1244  }
1245  return(result);
1246}
1247
1248///////////////////////////////////////////////////////////////////////////////
1249
1250proc Variables(poly f, int n)
1251"USAGE:   Variables(f,n); poly f; int n;
[9173792]1252PURPOSE: list of variables among var(1),...,var(n) which occur in f.
[4e461ff]1253RETURN:  list
1254ASSUME:  n <= nvars(basering)
1255"
1256{
1257  int i, nrV;
1258  list index;
1259
1260  nrV = 0;
1261  for(i = 1; i <= n; i = i + 1) {
1262    if(diff(f, var(i)) != 0) { nrV++; index[nrV] = i; }
1263  }
1264  return(index);
1265}
1266
1267///////////////////////////////////////////////////////////////////////////////
1268
[0bc582c]1269proc containedQ(data, f, list #)
1270"USAGE:    containedQ(data, f [, opt]); data=list; f=any type; opt=integer
[9173792]1271PURPOSE:  test if f is an element of data.
[4e461ff]1272RETURN:   int
[9173792]1273          0 if f not contained in data
1274          1 if f contained in data
1275OPTIONS:  opt = 0 : use '==' for comparing f with elements from data@*
[0bc582c]1276          opt = 1 : use @code{sameQ} for comparing f with elements from data
[4e461ff]1277"
1278{
1279  int opt, i, found;
1280  if(size(#) > 0) { opt = #[1];}
1281  else { opt = 0; }
1282  i = 1;
1283  found = 0;
1284
1285  while((!found) && (i <= size(data))) {
1286    if(opt == 0) {
1287      if(f == data[i]) { found = 1;}
1288      else {i = i + 1;}
1289    }
1290    else {
[0bc582c]1291      if(sameQ(f, data[i])) { found = 1;}
[4e461ff]1292      else {i = i + 1;}
1293    }
1294  }
1295  return(found);
1296}
1297
1298//////////////////////////////////////////////////////////////////////////////
1299
[0bc582c]1300proc sameQ(a, b)
1301"USAGE:    sameQ(a, b); a,b=list/intvec
[9173792]1302PURPOSE:  test a == b elementwise, i.e., a[i] = b[i].
[4e461ff]1303RETURN:   int
1304          0 if a != b
1305          1 if a == b
1306"
1307{
1308  if(typeof(a) == typeof(b)) {
1309    if(typeof(a) == "list" || typeof(a) == "intvec") {
1310      if(size(a) == size(b)) {
1311        int i = 1;
1312        int ok = 1;
1313        while(ok && (i <= size(a))) {
1314          if(a[i] == b[i]) { i = i + 1;}
1315          else {ok = 0;}
1316        }
1317        return(ok);
1318      }
1319      else { return(0); }
1320    }
1321    else { return(a == b);}
1322  }
1323  else { return(0);}
1324}
1325
1326///////////////////////////////////////////////////////////////////////////////
1327
1328static proc SimplifyPoly(poly f)
1329"USAGE:   SimplifyPoly(f); poly f
[9173792]1330PURPOSE: reduces the coefficients of f w.r.t. the ideal 'moly' if they contain
[4e461ff]1331         the algebraic number 'a'.
1332RETURN:  poly
1333ASSUME:  basering = Q[x_1,...,x_n,a]
1334         ideal mpoly must be defined, it might be 0 !
[980120f]1335NOTE: outdated, use reduce instead
[4e461ff]1336"
1337{
1338  matrix coMx;
1339  poly f1, vp;
1340
1341  vp = 1;
1342  for(int i = 1; i < nvars(basering); i++) { vp = vp * var(i);}
1343
1344  coMx = coef(f, vp);
1345  f1 = 0;
1346  for(i = 1; i <= ncols(coMx); i++) {
1347    f1 = f1 + coMx[1, i] * reduce(coMx[2, i], mpoly);
1348  }
1349  return(f1);
1350}
1351
1352///////////////////////////////////////////////////////////////////////////////
1353
1354static proc SimplifyData(data)
1355"USAGE:   SimplifyData(data); ideal/list data;
[9173792]1356PURPOSE: reduces the entries of 'data' w.r.t. the ideal 'mpoly' if they contain
[d12655]1357         the algebraic number 'a'
[4e461ff]1358RETURN:  ideal/list
1359ASSUME:  basering = Q[x_1,...,x_n,a]
1360         ideal 'mpoly' must be defined, it might be 0 !
1361"
1362{
[6fe3a0]1363  def altring=basering;
[4e461ff]1364  int n;
1365  poly f;
1366
1367  if(typeof(data) == "ideal") { n = ncols(data); }
1368  else { n = size(data);}
1369
1370  for(int i = 1; i <= n; i++) {
1371    f = data[i];
1372    data[i] = SimplifyPoly(f);
1373  }
1374  return(data);
1375}
1376
1377///////////////////////////////////////////////////////////////////////////////
1378
1379static proc TransferRing(R)
1380"USAGE:   TransferRing(R);
[9173792]1381PURPOSE: creates a new ring containing the same variables as R, but without
[4e461ff]1382         parameters. If R contains a parameter then this parameter is added
[d12655]1383         as the last variable and 'minpoly' is represented by the ideal 'mpoly'
1384         If the basering does not contain a parameter then 'a' is added and
1385         'mpoly' = 0.
[4e461ff]1386RETURN:  ring
1387ASSUME:  R = K[x_1,...,x_n] where K = Q or K = Q(a).
1388NOTE:    Creates the ring needed for all prodecures with name 'proc-name'Main
1389"
1390{
[6fe3a0]1391  def altring=basering;
[4e461ff]1392  string ringSTR, parName, minPoly;
1393
1394  setring(R);
1395
1396  if(npars(basering) == 0) {
1397    parName = "a";
1398    minPoly = "0";
1399  }
1400  else {
1401    parName = parstr(basering);
1402    minPoly = string(minpoly);
1403  }
1404  ringSTR = "ring TR = 0, (" + varstr(basering) + "," + parName + "), lp;";
1405
1406  execute(ringSTR);
1407  execute("ideal mpoly = std(" + minPoly + ");");
1408  export(mpoly);
[6fe3a0]1409  setring altring;
[4e461ff]1410  return(TR);
1411}
1412
1413///////////////////////////////////////////////////////////////////////////////
1414
1415static proc NewBaseRing()
1416"USAGE:   NewBaseRing();
[9173792]1417PURPOSE: creates a new ring, the last variable is added as a parameter.
[4e461ff]1418         minpoly is set to mpoly[1].
1419RETURN:  ring
1420ASSUME:  basering = Q[x_1,...,x_n, a], 'mpoly' must be defined
1421"
1422{
1423  int n = nvars(basering);
1424  int MP;
1425  string ringSTR, parName, varString;
1426
1427  def BR = basering;
1428  if(mpoly[1] != 0) {
1429    parName = "(0, " + string(var(n)) + ")";
1430    MP = 1;
1431  }
1432  else {
1433    parName = "0";
1434    MP = 0;
1435  }
1436
1437
1438  for(int i = 1; i < n - 1; i++) {
1439    varString = varString + string(var(i)) + ",";
1440  }
1441  varString = varString + string(var(n-1));
1442
1443  ringSTR = "ring TR = " + parName + ", (" + varString + "), lp;";
1444  execute(ringSTR);
1445  if(MP) { minpoly = number(imap(BR, mpoly)[1]); }
[6fe3a0]1446  setring BR;
[4e461ff]1447  return(TR);
1448}
1449
1450///////////////////////////////////////////////////////////////////////////////
1451
1452/*
1453                           Examples:
1454
1455
1456// order = 20;
1457ring S1 = 0, (s(1..3)), lp;
1458ideal I = s(2)*s(3), s(1)^2*s(2)+s(1)^2*s(3)-1, s(1)^2*s(3)^2-s(3), s(2)^4-s(3)^4+s(1)^2, s(1)^4+s(2)^3-s(3)^3, s(3)^5-s(1)^2*s(3);
[d12655]1459ideal mpoly = std(0);
[4e461ff]1460
1461// order = 10
1462ring S2 = 0, (s(1..5)), lp;
1463ideal I = s(2)+s(3)-s(5), s(4)^2-s(5), s(1)*s(5)+s(3)*s(4)-s(4)*s(5), s(1)*s(4)+s(3)-s(5), s(3)^2-2*s(3)*s(5), s(1)*s(3)-s(1)*s(5)+s(4)*s(5), s(1)^2+s(4)^2-2*s(5), -s(1)+s(5)^3, s(3)*s(5)^2+s(4)-s(5)^3, s(1)*s(5)^2-1;
[d12655]1464ideal mpoly = std(0);
[4e461ff]1465
1466//order = 126
1467ring S3 =  0, (s(1..5)), lp;
1468ideal I = s(3)*s(4), s(2)*s(4), s(1)*s(3), s(1)*s(2), s(3)^3+s(4)^3-1, s(2)^3+s(4)^3-1, s(1)^3-s(4)^3, s(4)^4-s(4), s(1)*s(4)^3-s(1), s(5)^7-1;
[d12655]1469ideal mpoly = std(0);
[4e461ff]1470
1471// order = 192
1472ring S4 = 0, (s(1..4)), lp;
1473ideal I = s(2)*s(3)^2*s(4)+s(1)*s(3)*s(4)^2, s(2)^2*s(3)*s(4)+s(1)*s(2)*s(4)^2, s(1)*s(3)^3+s(2)*s(4)^3, s(1)*s(2)*s(3)^2+s(1)^2*s(3)*s(4), s(1)^2*s(3)^2-s(2)^2*s(4)^2, s(1)*s(2)^2*s(3)+s(1)^2*s(2)*s(4), s(1)^3*s(3)+s(2)^3*s(4), s(2)^4-s(3)^4, s(1)*s(2)^3+s(3)*s(4)^3, s(1)^2*s(2)^2-s(3)^2*s(4)^2, s(1)^3*s(2)+s(3)^3*s(4), s(1)^4-s(4)^4, s(3)^5*s(4)-s(3)*s(4)^5, s(3)^8+14*s(3)^4*s(4)^4+s(4)^8-1, 15*s(2)*s(3)*s(4)^7-s(1)*s(4)^8+s(1), 15*s(3)^4*s(4)^5+s(4)^9-s(4), 16*s(3)*s(4)^9-s(3)*s(4), 16*s(2)*s(4)^9-s(2)*s(4), 16*s(1)*s(3)*s(4)^8-s(1)*s(3), 16*s(1)*s(2)*s(4)^8-s(1)*s(2), 16*s(1)*s(4)^10-15*s(2)*s(3)*s(4)-16*s(1)*s(4)^2, 16*s(1)^2*s(4)^9-15*s(1)*s(2)*s(3)-16*s(1)^2*s(4), 16*s(4)^13+15*s(3)^4*s(4)-16*s(4)^5;
[d12655]1474ideal mpoly = std(0);
[4e461ff]1475
1476ring R = (0,a), (x,y,z), lp;
1477minpoly = a2 + 1;
1478ideal I1 = x2 - 1/2, a*z - 1, y - 2;
1479ideal I2 = x3 - 1/2, a*z2 - 3, y - 2*a;
[35f23d]1480
[d12655]1481*/
Note: See TracBrowser for help on using the repository browser.