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

spielwiese
Last change on this file since b2222d was b2222d, checked in by Sachin <sachinkm308@…>, 4 years ago
replacing execute with create_ring(12) All pending ring file changes and solve.lib changes
  • Property mode set to 100644
File size: 45.2 KB
Line 
1////////////////////////////////////////////////////////////////////////////
2version="version zeroset.lib 4.1.2.0 Feb_2019 "; // $Id$
3category="Symbolic-numerical solving";
4info="
5LIBRARY:  zeroset.lib      Procedures for roots and factorization
6AUTHOR:   Thomas Bayer,    email: tbayer@mathematik.uni-kl.de,@*
7          http://wwwmayr.informatik.tu-muenchen.de/personen/bayert/@*
8          Current address: Hochschule Ravensburg-Weingarten
9
10OVERVIEW:
11 Algorithms for finding the zero-set of a zero-dim. ideal in Q(a)[x_1,..,x_n],
12 roots and factorization of univariate polynomials over Q(a)[t]
13 where a is an algebraic number. Written in the scope of the
14 diploma thesis (advisor: Prof. Gert-Martin Greuel) 'Computations of moduli
15 spaces of semiquasihomogeneous singularities and an implementation in Singular'.
16 This library is meant as a preliminary extension of the functionality
17 of Singular for univariate factorization of polynomials over simple algebraic
18 extensions in characteristic 0.
19
20NOTE:
21 Subprocedures with postfix 'Main' require that the ring contains a variable
22 'a' and no parameters, and the ideal 'mpoly', where 'minpoly' from the
23 basering is stored.
24
25PROCEDURES:
26 Quotient(f, g)    quotient q  of f w.r.t. g (in f = q*g + remainder)
27 remainder(f,g)    remainder of the division of f by g
28 roots(f)    computes all roots of f in an extension field of Q
29 sqfrNorm(f)    norm of f (f must be squarefree)
30 zeroSet(I)    zero-set of the 0-dim. ideal I
31
32 egcdMain(f, g)    gcd over an algebraic extension field of Q
33 factorMain(f)    factorization of f over an algebraic extension field
34 invertNumberMain(c)  inverts an element of an algebraic extension field
35 quotientMain(f, g)  quotient of f w.r.t. g
36 remainderMain(f,g)  remainder of the division of f by g
37 rootsMain(f)    computes all roots of f, might extend the ground field
38 sqfrNormMain(f)  norm of f (f must be squarefree)
39 containedQ(data, f)  f in data ?
40 sameQ(a, b)    a == b (list a,b)
41";
42
43LIB "primitiv.lib";
44LIB "primdec.lib";
45
46// note : return a ring : ring need not be exported !!!
47
48// Artihmetic in Q(a)[x] without built-in procedures
49// assume basering = Q[x,a] and minpoly is represented by mpoly(a).
50// the algorithms are taken from "Polynomial Algorithms in Computer Algebra",
51// F. Winkler, Springer Verlag Wien, 1996.
52
53
54// To do :
55// squarefree factorization
56// multiplicities
57
58// Improvement :
59// a main problem is the growth of the coefficients. Try roots(x7 - 1)
60// return ideal mpoly !
61// mpoly is not monic, comes from primitive_extra
62
63// IMPLEMENTATION
64//
65// In procedures with name 'proc-name'Main a polynomial ring over a simple
66// extension field is represented as Q[x...,a] together with the ideal
67// 'mpoly' (attribute "isSB"). The arithmetic in the extension field is
68// implemented in the procedures in the procedures 'MultPolys' (multiplication)
69// and 'InvertNumber' (inversion). After addition and substraction one should
70// apply 'SimplifyPoly' to the result to reduce the result w.r.t. 'mpoly'.
71// This is done by reducing each coefficient seperately, which is more
72// efficient for polynomials with many terms.
73
74
75///////////////////////////////////////////////////////////////////////////////
76
77proc roots(poly f)
78"USAGE:   roots(f); where f is a polynomial
79PURPOSE: compute all roots of f in a finite extension of the ground field
80         without multiplicities.
81RETURN:  ring, a polynomial ring over an extension field of the ground field,
82         containing a list 'theRoots' and polynomials 'newA' and 'f':
83  @format
84  - 'theRoots' is the list of roots of the polynomial f (no multiplicities)
85  - if the ground field is Q(a') and the extension field is Q(a), then
86    'newA' is the representation of a' in Q(a).
87    If the basering contains a parameter 'a' and the minpoly remains unchanged
88    then 'newA' = 'a'.
89    If the basering does not contain a parameter then 'newA' = 'a' (default).
90  - 'f' is the polynomial f in Q(a) (a' being substituted by 'newA')
91  @end format
92ASSUME:  ground field to be Q or a simple extension of Q given by a minpoly
93EXAMPLE: example roots; shows an example
94"
95{
96  int dbPrt = printlevel-voice+3;
97
98  // create a new ring where par(1) is replaced by the variable
99  // with the same name or, if basering does not contain a parameter,
100  // with a new variable 'a'.
101
102  def ROB = basering;
103  def ROR = TransferRing(basering);
104  setring ROR;
105  export(ROR);
106
107  // get the polynomial f and find the roots
108
109  poly f = imap(ROB, f);
110  list result = rootsMain(f);  // find roots of f
111
112  // store the roots and the new representation of 'a' and transform
113  // the coefficients of f.
114
115  list theRoots = result[1];
116  poly newA = result[2];
117  map F = basering, maxideal(1);
118  F[nvars(basering)] = newA;
119  poly fn = SimplifyPoly(F(f));
120
121  // create a new ring with minploy = mpoly[1] (from ROR)
122
123  def RON = NewBaseRing();
124  setring(RON);
125  list theRoots = imap(ROR, theRoots);
126  poly newA = imap(ROR, newA);
127  poly f = imap(ROR, fn);
128  kill ROR;
129  export(theRoots);
130  export(newA);
131  export(f); dbprint(dbPrt,"
132// 'roots' created a new ring which contains the list 'theRoots' and
133// the polynomials 'f' and 'newA'
134// To access the roots, newA and the new representation of f, type
135   def R = roots(f); setring R; theRoots; newA; f;
136");
137  return(RON);
138}
139example
140{"EXAMPLE:";  echo = 2;
141  ring R = (0,a), x, lp;
142  minpoly = a2+1;
143  poly f = x3 - a;
144  def R1 = roots(f);
145  setring R1;
146  minpoly;
147  newA;
148  f;
149  theRoots;
150  map F;
151  F[1] = theRoots[1];
152  F(f);
153}
154
155///////////////////////////////////////////////////////////////////////////////
156
157proc rootsMain(poly f)
158"USAGE:   rootsMain(f); where f is a polynomial
159PURPOSE: compute all roots of f in a finite extension of the ground field
160         without multiplicities.
161RETURN:  list, all entries are polynomials
162  @format
163  _[1] = roots of f, each entry is a polynomial
164  _[2] = 'newA' - if the ground field is Q(b) and the extension field
165         is Q(a), then 'newA' is the representation of b in Q(a)
166  _[3] = minpoly of the algebraic extension of the ground field
167  @end format
168ASSUME:  basering = Q[x,a] ideal mpoly must be defined, it might be 0!
169NOTE:    might change the ideal mpoly!!
170EXAMPLE: example rootsMain; shows an example
171"
172{
173  int i, linFactors, nlinFactors, dbPrt;
174  intvec wt = 1,0;    // deg(a) = 0
175  list factorList, nlFactors, nlMult, roots, result;
176  poly fa, lc;
177
178  dbPrt = printlevel-voice+3;
179
180  // factor f in Q(a)[t] to obtain the roots lying in Q(a)
181  // firstly, find roots of the linear factors,
182  // nonlinear factors are processed later
183
184  dbprint(dbPrt, "roots of " + string(f) +  ", minimal polynomial = " + string(mpoly[1]));
185  factorList = factorMain(f);          // Factorize f
186  dbprint(dbPrt, (" prime factors of f are : " + string(factorList[1])));
187
188  linFactors = 0;
189  nlinFactors = 0;
190  for(i = 2; i <= size(factorList[1]); i = i + 1) {  // find linear and nonlinear factors
191    fa = factorList[1][i];
192    if(deg(fa, wt) == 1) {
193      linFactors++;        // get the root from the linear factor
194      lc = LeadTerm(fa, 1)[3];
195      fa = MultPolys(invertNumberMain(lc), fa); // make factor monic
196      roots[linFactors] = var(1) - fa;  // fa is monic !!
197    }
198    else {            // ignore nonlinear factors
199      nlinFactors++;
200      nlFactors[nlinFactors] = factorList[1][i];
201      nlMult[nlinFactors] = factorList[2][i];
202    }
203  }
204  if(linFactors == size(factorList[1]) - 1) {    // all roots of f are contained in the ground field
205    result[1] = roots;
206    result[2] = var(2);
207    result[3] = mpoly[1];
208    return(result);
209  }
210
211  // process the nonlinear factors, i.e., extend the ground field
212  // where a nonlinear factor (irreducible) is a minimal polynomial
213  // compute the primitive element of this extension
214
215  ideal primElem, minPolys, Fid;
216  list partSol;
217  map F, Xchange;
218  poly f1, newA, mp, oldMinPoly;
219
220  Fid = mpoly;
221  F[1] = var(1);
222  Xchange[1] = var(2);      // the variables have to be exchanged
223  Xchange[2] = var(1);      // for the use of 'primitive'
224
225  if(nlinFactors == 1)             // one nl factor
226  {
227    // compute the roots of the nonlinear (irreducible, monic) factor f1 of f
228    // by extending the basefield by a' with minimal polynomial f1
229    // Then call roots(f1) to find the roots of f1 over the new base field
230
231    f1 = nlFactors[1];
232    if(mpoly[1] != 0)
233    {
234      mp = mpoly[1];
235      minPolys = Xchange(mp), Xchange(f1);
236      if (deg(jet(minPolys[2],0,intvec(1,0)))==0)
237      { primElem = primitive(minPolys); } // random coord. change
238      else
239      { primElem = primitive_extra(minPolys); } // no random coord. change
240      mpoly = std(primElem[1]);
241      F = basering, maxideal(1);
242      F[2] = primElem[2];      // transfer all to the new representation
243      newA = primElem[2];      // new representation of a
244      f1 = SimplifyPoly(F(f1));     //reduce(F(f1), mpoly);
245      if(size(roots) > 0) {roots = SimplifyData(F(roots));}
246    }
247    else {
248      mpoly = std(Xchange(f1));
249      newA = var(2);
250    }
251    result[3] = mpoly[1];
252    oldMinPoly = mpoly[1];
253    partSol = rootsMain(f1);    // find roots of f1 over extended field
254
255    if(oldMinPoly != partSol[3]) {    // minpoly has changed ?
256      // all previously computed roots must be transformed
257      // because the minpoly has changed
258      result[3] = partSol[3];    // new minpoly
259      F[2] = partSol[2];    // new representation of algebraic number
260      if(size(roots) > 0) {roots = SimplifyData(F(roots)); }
261      newA = SimplifyPoly(F(newA)); // F(newA);
262    }
263    roots = roots + partSol[1];  // add roots
264    result[2] = newA;
265    result[1] = roots;
266  }
267  else {  // more than one nonlinear (irreducible) factor (f_1,...,f_r)
268    // solve each of them by rootsMain(f_i), append their roots
269    // change the minpoly and transform all previously computed
270    // roots if necessary.
271    // Note that the for-loop is more or less book-keeping
272
273    newA = var(2);
274    result[2] = newA;
275    for(i = 1; i <= size(nlFactors); i = i + 1) {
276      oldMinPoly = mpoly[1];
277      partSol = rootsMain(nlFactors[i]);    // main work
278      nlFactors[i] = 0;        // delete factor
279      result[3] = partSol[3];        // store minpoly
280
281      // book-keeping starts here as in the case 1 nonlinear factor
282
283      if(oldMinPoly != partSol[3]) { // minpoly has changed
284        F = basering, maxideal(1);
285        F[2] = partSol[2];    // transfer all to the new representation
286        newA = SimplifyPoly(F(newA));    // F(newA); new representation of a
287        result[2] = newA;
288        if(i < size(nlFactors)) {
289          nlFactors = SimplifyData(F(nlFactors));
290        } // transform remaining factors
291        if(size(roots) > 0) {roots = SimplifyData(F(roots));}
292      }
293      roots = roots + partSol[1];    // transform roots
294      result[1] = roots;
295    }  // end more than one nl factor
296
297  }
298  return(result);
299}
300
301///////////////////////////////////////////////////////////////////////////////
302
303proc zeroSet(ideal I, list #)
304"USAGE:   zeroSet(I [,opt] ); I=ideal, opt=integer
305PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension
306         of the ground field.
307RETURN:  ring, a polynomial ring over an extension field of the ground field,
308         containing a list 'theZeroset', a polynomial 'newA', and an
309         ideal 'id':
310  @format
311  - 'theZeroset' is the list of the zeros of the ideal I, each zero is an ideal.
312  - if the ground field is Q(b) and the extension field is Q(a), then
313    'newA' is the representation of b in Q(a).
314    If the basering contains a parameter 'a' and the minpoly remains unchanged
315    then 'newA' = 'a'.
316    If the basering does not contain a parameter then 'newA' = 'a' (default).
317  - 'id' is the ideal I in Q(a)[x_1,...] (a' substituted by 'newA')
318  @end format
319ASSUME:  dim(I) = 0, and ground field to be Q or a simple extension of Q given
320         by a minpoly.
321OPTIONS: opt = 0: no primary decomposition (default)
322         opt > 0: primary decomposition
323NOTE:    If I contains an algebraic number (parameter) then I must be
324         transformed w.r.t. 'newA' in the new ring.
325EXAMPLE: example zeroSet; shows an example
326"
327{
328  int primaryDecQ, dbPrt;
329  list rp;
330
331  dbPrt = printlevel-voice+2;
332
333  if(size(#) > 0) { primaryDecQ = #[1]; }
334  else { primaryDecQ = 0; }
335
336  // create a new ring 'ZSR' with one additional variable instead of the
337  // parameter
338  // if the basering does not contain a parameter then 'a' is used as the
339  // additional variable.
340
341  def RZSB = basering;
342  def ZSR = TransferRing(RZSB);
343  setring ZSR;
344
345  // get ideal I and find the zero-set
346
347  ideal id = std(imap(RZSB, I));
348//  print(dim(id));
349  if(dim(id) > 1) {       // new variable adjoined to ZSR
350    ERROR(" ideal not zerodimensional ");
351  }
352
353  list result = zeroSetMain(id, primaryDecQ);
354
355  // store the zero-set, minimal polynomial and the new representative of 'a'
356
357  list theZeroset = result[1];
358  poly newA = result[2];
359  poly minPoly = result[3][1];
360
361  // transform the generators of the ideal I w.r.t. the new representation
362  // of 'a'
363
364  map F = basering, maxideal(1);
365  F[nvars(basering)] = newA;
366  id = SimplifyData(F(id));
367
368  // create a new ring with minpoly = minPoly
369
370  def RZBN = NewBaseRing();
371  setring RZBN;
372
373  list theZeroset = imap(ZSR, theZeroset);
374  poly newA = imap(ZSR, newA);
375  ideal id = imap(ZSR, id);
376  kill ZSR;
377
378  export(id);
379  export(theZeroset);
380  export(newA);
381    dbprint(dbPrt,"
382// 'zeroSet' created a new ring which contains the list 'theZeroset', the ideal
383// 'id' and the polynomial 'newA'. 'id' is the ideal of the input transformed
384// w.r.t. 'newA'.
385// To access the zero-set, 'newA' and the new representation of the ideal, type
386   def R = zeroSet(I); setring R; theZeroset; newA; id;
387");
388  setring RZSB;
389  return(RZBN);
390}
391example
392{"EXAMPLE:";  echo = 2;
393  ring R = (0,a), (x,y,z), lp;
394  minpoly = a2 + 1;
395  ideal I = x2 - 1/2, a*z - 1, y - 2;
396  def T = zeroSet(I);
397  setring T;
398  minpoly;
399  newA;
400  id;
401  theZeroset;
402  map F1 = basering, theZeroset[1];
403  map F2 = basering, theZeroset[2];
404  F1(id);
405  F2(id);
406}
407
408///////////////////////////////////////////////////////////////////////////////
409
410proc invertNumberMain(poly f)
411"USAGE:   invertNumberMain(f); where f is a polynomial
412PURPOSE: compute 1/f if f is a number in Q(a), i.e., f is represented by a
413         polynomial in Q[a].
414RETURN:  poly 1/f
415ASSUME:  basering = Q[x_1,...,x_n,a], ideal mpoly must be defined and != 0 !
416NOTE:    outdated, use / instead
417"
418{
419  if(diff(f, var(1)) != 0) { ERROR("number must not contain variable !");}
420
421  int n = nvars(basering);
422  def RINB = basering;
423  ring RINR = create_ring(0, string(var(n)), "dp");       // new ring = Q[a]
424
425  list gcdList;
426  poly f, g, inv;
427
428  f = imap(RINB, f);
429  g = imap(RINB, mpoly)[1];
430
431  if(diff(f, var(1)) != 0) { inv = extgcd(f, g)[2]; }  // f contains var(1)
432  else {  inv = 1/f;}          // f element in Q
433
434  setring(RINB);
435  return(imap(RINR, inv));
436}
437
438///////////////////////////////////////////////////////////////////////////////
439
440proc MultPolys(poly f, poly g)
441"USAGE:   MultPolys(f, g); poly f,g
442PURPOSE: multiply the polynomials f and g and reduce them w.r.t. mpoly
443RETURN:  poly f*g
444ASSUME:  basering = Q[x,a], ideal mpoly must be defined, it might be 0 !
445"
446{
447  return(SimplifyPoly(f * g));
448}
449
450///////////////////////////////////////////////////////////////////////////////
451
452proc LeadTerm(poly f, int i)
453"USAGE:   LeadTerm(f); poly f, int i
454PURPOSE: compute the leading coef and term of f w.r.t var(i), where the last
455         ring variable is treated as a parameter.
456RETURN:  list of polynomials
457         _[1] = leading term
458         _[2] = leading monomial
459         _[3] = leading coefficient
460ASSUME:  basering = Q[x_1,...,x_n,a]
461"
462{
463  list result;
464  matrix co = coef(f, var(i));
465  result[1] = co[1, 1]*co[2, 1];
466  result[2] = co[1, 1];
467  result[3] = co[2, 1];
468  return(result);
469}
470
471///////////////////////////////////////////////////////////////////////////////
472
473proc Quotient(poly f, poly g)
474"USAGE:   Quotient(f, g); where f,g are polynomials;
475PURPOSE: compute the quotient q and remainder r s.t. f = g*q + r, deg(r) < deg(g)
476RETURN:  list of polynomials
477  @format
478  _[1] = quotient  q
479  _[2] = remainder r
480  @end format
481ASSUME:  basering = Q[x] or Q(a)[x]
482NOTE: This procedure is outdated, and should no longer be used. Use div and mod
483instead.
484EXAMPLE: example Quotient; shows an example
485"
486{
487  def QUOB = basering;
488  def QUOR = TransferRing(basering);  // new ring with parameter 'a' replaced by a variable
489  setring QUOR;
490  export(QUOR);
491  poly f = imap(QUOB, f);
492  poly g = imap(QUOB, g);
493  list result = quotientMain(f, g);
494
495  setring(QUOB);
496  list result = imap(QUOR, result);
497  kill QUOR;
498  return(result);
499}
500example
501{"EXAMPLE:";  echo = 2;
502 ring R = (0,a), x, lp;
503 minpoly = a2+1;
504 poly f =  x4 - 2;
505 poly g = x - a;
506 list qr = Quotient(f, g);
507 qr;
508 qr[1]*g + qr[2] - f;
509}
510
511proc quotientMain(poly f, poly g)
512"USAGE:   quotientMain(f, g); where f,g are polynomials
513PURPOSE: compute the quotient q and remainder r s.th. f = g*q + r, deg(r) < deg(g)
514RETURN:  list of polynomials
515  @format
516  _[1] = quotient  q
517  _[2] = remainder r
518  @end format
519ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
520         this represents the ring Q(a)[x] together with its minimal polynomial.
521NOTE: outdated, use div/mod instead
522"
523{
524  if(g == 0) { ERROR("Division by zero !");}
525
526  def QMB = basering;
527  def QMR = NewBaseRing();
528  setring QMR;
529  poly f, g, h;
530  h = imap(QMB, f) / imap(QMB, g);
531  setring QMB;
532  return(list(imap(QMR, h), 0));
533}
534
535///////////////////////////////////////////////////////////////////////////////
536
537proc remainder(poly f, poly g)
538"USAGE:   remainder(f, g); where f,g are polynomials
539PURPOSE: compute the remainder of the division of f by g, i.e. a polynomial r
540         s.t. f = g*q + r, deg(r) < deg(g).
541RETURN:  poly
542ASSUME:  basering = Q[x] or Q(a)[x]
543NOTE: outdated, use mod/reduce instead
544"
545{
546  def REMB = basering;
547  def REMR = TransferRing(basering);  // new ring with parameter 'a' replaced by a variable
548  setring(REMR);
549  export(REMR);
550  poly f = imap(REMB, f);
551  poly g = imap(REMB, g);
552  poly h = remainderMain(f, g);
553
554  setring(REMB);
555  poly r = imap(REMR, h);
556  kill REMR;
557  return(r);
558}
559example
560{"EXAMPLE:";  echo = 2;
561 ring R = (0,a), x, lp;
562 minpoly = a2+1;
563 poly f =  x4 - 1;
564 poly g = x3 - 1;
565 remainder(f, g);
566}
567
568proc remainderMain(poly f, poly g)
569"USAGE:   remainderMain(f, g); where f,g are polynomials
570PURPOSE: compute the remainder r s.t. f = g*q + r, deg(r) < deg(g)
571RETURN:  poly
572ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
573         this represents the ring Q(a)[x] together with its minimal polynomial.
574NOTE: outdated, use mod/reduce instead
575"
576{
577  int dg;
578  intvec wt = 1,0;;
579  poly lc, g1, r;
580
581  if(deg(g, wt) == 0) { return(0); }
582
583  lc = LeadTerm(g, 1)[3];
584  g1 = MultPolys(invertNumberMain(lc), g);  // make g monic
585
586  return(SimplifyPoly(reduce(f, std(g1))));
587}
588
589///////////////////////////////////////////////////////////////////////////////
590
591proc egcdMain(poly f, poly g)
592"USAGE:   egcdMain(f, g); where f,g are polynomials
593PURPOSE: compute the polynomial gcd of f and g over Q(a)[x]
594RETURN:  poly
595ASSUME:  basering = Q[x,a] and ideal mpoly is defined (it might be 0),
596         this represents the ring Q(a)[x] together with its minimal polynomial.
597NOTE: outdated, use gcd instead
598EXAMPLE: example EGCD; shows an example
599"
600{
601// might be extended to return s1, s2 s.t. f*s1 + g*s2 = gcd
602  int i = 1;
603  poly r1, r2, r;
604
605  r1 = f;
606  r2 = g;
607
608  while(r2 != 0) {
609    r  = remainderMain(r1, r2);
610    r1 = r2;
611    r2 = r;
612  }
613  return(r1);
614}
615
616///////////////////////////////////////////////////////////////////////////////
617
618proc MEGCD(poly f, poly g, int varIndex)
619"USAGE:   MEGCD(f, g, i); poly f, g; int i
620PURPOSE: compute  the polynomial gcd of f and g in the i'th variable
621RETURN:  poly
622ASSUME:  f, g are polynomials in var(i), last variable is the algebraic number
623EXAMPLE: example MEGCD; shows an example
624"
625// might be extended to return s1, s2 s.t. f*s1 + g*s2 = gc
626// not used !
627{
628  string @str, @sf, @sg, @mp, @parName;
629
630  def @RGCDB = basering;
631
632  @sf = string(f);
633  @sg = string(g);
634  @mp = string(minpoly);
635
636  if(npars(basering) == 0) { @parName = "0";}
637  else { @parName = "(0, " + parstr(basering) + ")"; }
638  ring @RGCD = create_ring(@parName, string(var(varIndex)), "dp");
639  if(@mp != "0") { execute ("minpoly = " + @mp + ";"); }
640  execute("poly @f = " + @sf + ";");
641  execute("poly @g = " + @sg + ";");
642  export(@RGCD);
643  poly @h = gcd(@f, @g);
644  setring(@RGCDB);
645  poly h = imap(@RGCD, @h);
646  kill @RGCD;
647  return(h);
648}
649
650///////////////////////////////////////////////////////////////////////////////
651
652proc sqfrNorm(poly f)
653"USAGE:   sqfrNorm(f); where f is a polynomial
654PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x].
655RETURN:  list with 3 entries
656  @format
657  _[1] = squarefree norm of g (poly)
658  _[2] = g (= f(x - s*a)) (poly)
659  _[3] = s (int)
660  @end format
661ASSUME:  f must be squarefree, basering = Q(a)[x] and minpoly != 0.
662NOTE:    the norm is an element of Q[x]
663EXAMPLE: example sqfrNorm; shows an example
664"
665{
666  def SNB = basering;
667  def SNR = TransferRing(SNB);  // new ring with parameter 'a'
668                                // replaced by a variable
669  setring SNR;
670  poly f = imap(SNB, f);
671  list result = sqfrNormMain(f);  // squarefree norm of f
672
673  setring SNB;
674  list result = imap(SNR, result);
675  kill SNR;
676  return(result);
677}
678example
679{"EXAMPLE:";  echo = 2;
680   ring R = (0,a), x, lp;
681   minpoly = a2+1;
682  poly f =  x4 - 2*x + 1;
683  sqfrNorm(f);
684}
685
686proc sqfrNormMain(poly f)
687"USAGE:   sqfrNorm(f); where f is a polynomial
688PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x].
689RETURN:  list with 3 entries
690  @format
691  _[1] = squarefree norm of g (poly)
692  _[2] = g (= f(x - s*a)) (poly)
693  _[3] = s (int)
694  @end format
695ASSUME:  f must be squarefree, basering = Q[x,a] and ideal mpoly is equal to
696         'minpoly', this represents the ring Q(a)[x] together with 'minpoly'.
697NOTE:   the norm is an element of Q[x]
698EXAMPLE: example SqfrNorm; shows an example
699"
700{
701  def SNRMB = basering;
702  int s = 0;
703  intvec wt = 1,0;
704  ideal mapId;
705  // list result;
706  poly g, N, N1, h;
707  string ringSTR;
708
709  mapId[1] = var(1) - var(2);    // linear transformation
710  mapId[2] = var(2);
711  map Fs = SNRMB, mapId;
712
713  N = resultant(f, mpoly[1], var(2));  // norm of f
714  N1 = diff(N, var(1));
715  g = f;
716
717  ring SNRM1 = create_ring(0, string(var(1)), "dp");     // univariate ring
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
737proc factorMain(poly f)
738"USAGE:   factorMain(f); where f is a polynomial
739PURPOSE: compute the factorization of the squarefree polynomial f over Q(a)[t],
740         minpoly  = p(a).
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!).
748NOTE: outdated, use factorize instead
749EXAMPLE: example Factor; shows an example
750"
751{
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;
774  normList = sqfrNormMain(f);
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];
785    h = egcdMain(H, g);
786    quo_rem = quotientMain(g, h);
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
796proc zeroSetMain(ideal I, int primDecQ)
797"USAGE:   zeroSetMain(ideal I, int opt); ideal I, int opt
798PURPOSE: compute the zero-set of the zero-dim. ideal I, in a simple extension
799         of the ground field.
800RETURN:  list
801         - 'f' is the polynomial f in  Q(a) (a' being substituted by newA)
802         _[1] = zero-set (list), is the list of the zero-set of the ideal I,
803                each entry is an ideal.
804         _[2] = 'newA';  if the ground field is Q(a') and the extension field
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).
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.
813NOTE:    opt = 0  no primary decomposition
814         opt > 0  use a primary decomposition
815EXAMPLE: example zeroSetMain; shows an example
816"
817{
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
820  // minpoly and the parameter representing the algebraic extension are
821  // transformed according to 'newA', i.e., only bookeeping is done.
822
823  def altring=basering;
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;
832  dbprint(dbPrt, "zeroSet of " + string(I) + ", minpoly = " + string(minpoly));
833
834  n = nvars(basering) - 1;
835  for(i = 1; i <= n; i++) { w[i] = 1;}
836  w[n + 1] = 0;
837
838  if(primDecQ == 0) { return(zeroSetMainWork(I, w, 0)); }
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.
854  // If necessary, change the ground field and transform the zero-set
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));
865    currentSol = zeroSetMainWork(J, w, 0);
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
886proc zeroSetMainWork(ideal id, intvec wt, int sVars)
887"USAGE:   zeroSetMainWork(I, wt, sVars);
888PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension
889         of the ground field (without multiplicities).
890RETURN:  list, all entries are polynomials
891         _[1] = zeros, each entry is an ideal
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)
894         _[4] = name of algebraic number (default = 'a')
895ASSUME:  basering = Q[x_1,x_2,...,x_n,a]
896         ideal mpoly must be defined, it might be 0!
897NOTE:    might change 'mpoly' !!
898EXAMPLE: example IdealSolve; shows an example
899"
900{
901  def altring=basering;
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
961  // of zeroSetMainWork !
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];
971    partSol = zeroSetMainWork(gens, wt, size(index) + sVars);
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{
1011  def altring=basering;
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];
1031        sol[nrSols] = var(vars[1]) - MultPolys(invertNumberMain(LeadTerm(f, vars[1])[3]), f);
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)
1053"USAGE:   NonLinearZeroSetMain(I, wt);
1054PURPOSE: solves the (nonlinear) univariate polynomials in I
1055         of the ground field (without multiplicities).
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;
1075  export(NLZR);
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      ring RIS1 = create_ring(0, "(" + string(var(vars[1])) + ", " + string(var(n+1)) + ")", "lp");
1100      ideal mpoly = std(imap(NLZR, mpoly));
1101      list roots;
1102      poly f = imap(NLZR, f);
1103      export(RIS1);
1104      export(mpoly);
1105      roots = rootsMain(f);
1106
1107      // get "old" basering with new minpoly
1108
1109      setring(NLZR);
1110      partSol = imap(RIS1, roots);
1111      kill RIS1;
1112      if(mpoly[1] != partSol[3]) {      // change minpoly
1113        mpoly = std(partSol[3]);
1114        F = NLZR, maxideal(1);
1115        F[n + 1] = partSol[2];
1116        if(size(sols) > 0) {sols = SimplifyZeroset(F(sols)); }
1117        newA = reduce(F(newA), mpoly);    // normal form
1118        result[2] = newA;
1119        generators = SimplifyData(F(generators));  // does not remove 0's
1120      }
1121      sols = ExtendSolutions(sols, partSol[1]);
1122    } // end univariate
1123    else {
1124      i = i + 1;
1125    }
1126    if(i > size(generators)) { ok = 0;}
1127  }
1128  result[1] = sols;
1129  result[3] = mpoly;
1130  result[4] = index;
1131  result[5] = std(generators);
1132
1133  kill NLZR;
1134  return(result);
1135}
1136
1137///////////////////////////////////////////////////////////////////////////////
1138
1139static proc ExtendSolutions(list solutions, list newSolutions)
1140"USAGE:   ExtendSolutions(sols, newSols); list sols, newSols;
1141PURPOSE: extend the entries of 'sols' by the entries of 'newSols',
1142         each entry of 'newSols' is a number.
1143RETURN:  list
1144ASSUME:  basering = Q[x_1,...,x_n,a], ideal 'mpoly' must be defined,
1145         it might be 0 !
1146NOTE:    used by 'NonLinearZeroSetMain'
1147"
1148{
1149  int i, j, k, n, nrSols;
1150  list newSols, temp;
1151
1152  nrSols = size(solutions);
1153  if(nrSols > 0) {n = size(solutions[1]);}
1154  else {
1155    n = 0;
1156    nrSols = 1;
1157  }
1158  k = 0;
1159  for(i = 1; i <= nrSols; i++) {
1160    for(j = 1; j <= size(newSolutions); j++) {
1161      k++;
1162      if(n == 0) { temp[1] = newSolutions[j];}
1163      else {
1164        temp = solutions[i];
1165        temp[n + 1] = newSolutions[j];
1166      }
1167      newSols[k] = temp;
1168    }
1169  }
1170  return(newSols);
1171}
1172
1173///////////////////////////////////////////////////////////////////////////////
1174
1175static proc MergeSolutions(list sol1, list index1, list sol2, list index2)
1176"USAGE:   MergeSolutions(sol1, index1, sol2, index2); all parameters are lists
1177RETURN:  list
1178PURPOSE: create a list of solutions of size n, each entry of 'sol2' must
1179         have size n. 'sol1' is one partial solution (from 'LinearZeroSetMain')
1180         'sol2' is a list of partial solutions (from 'NonLinearZeroSetMain')
1181ASSUME:  'sol2' is not empty
1182NOTE:    used by 'zeroSetMainWork'
1183{
1184  int i, j, k, m;
1185  ideal sol;
1186  list newSols;
1187
1188  m = 0;
1189  for(i = 1; i <= size(sol2); i++) {
1190    m++;
1191    newSols[m] = SubsMapIdeal(sol1 + sol2[i], index1 + index2, 0);
1192  }
1193  return(newSols);
1194}
1195
1196///////////////////////////////////////////////////////////////////////////////
1197
1198static proc SubsMapIdeal(list sol, list index, int opt)
1199"USAGE:   SubsMapIdeal(sol,index,opt); list sol, index; int opt;
1200PURPOSE: built an ideal I as follows.
1201         if i is contained in 'index' then set I[i] = sol[i]
1202         if i is not contained in 'index' then
1203         - opt = 0: set I[i] = 0
1204         - opt = 1: set I[i] = var(i)
1205         if opt = 1 and n = nvars(basering) then set I[n] = var(n).
1206RETURN:  ideal
1207ASSUME:  size(sol) = size(index) <= nvars(basering)
1208"
1209{
1210  int k = 0;
1211  ideal I;
1212  for(int i = 1; i <= nvars(basering) - 1; i = i + 1) {    // built subs. map
1213    if(containedQ(index, i)) {
1214      k++;
1215      I[index[k]] = sol[k];
1216    }
1217    else {
1218      if(opt) { I[i] = var(i); }
1219      else { I[i] = 0; }
1220    }
1221  }
1222  if(opt) {I[nvars(basering)] = var(nvars(basering));}
1223  return(I);
1224}
1225
1226///////////////////////////////////////////////////////////////////////////////
1227
1228proc SimplifyZeroset(def data)
1229"USAGE:   SimplifyZeroset(data); list data
1230PURPOSE: reduce the entries of the elements of 'data' w.r.t. the ideal 'mpoly'
1231         'data' is a list of ideals/lists.
1232RETURN:  list
1233ASSUME:  basering = Q[x_1,...,x_n,a], order = lp
1234         'data' is a list of ideals
1235         ideal 'mpoly' must be defined, it might be 0 !
1236"
1237{
1238  int i;
1239  list result;
1240
1241  for(i = 1; i <= size(data); i++) {
1242    result[i] = SimplifyData(data[i]);
1243  }
1244  return(result);
1245}
1246
1247///////////////////////////////////////////////////////////////////////////////
1248
1249proc Variables(poly f, int n)
1250"USAGE:   Variables(f,n); poly f; int n;
1251PURPOSE: list of variables among var(1),...,var(n) which occur in f.
1252RETURN:  list
1253ASSUME:  n <= nvars(basering)
1254"
1255{
1256  int i, nrV;
1257  list index;
1258
1259  nrV = 0;
1260  for(i = 1; i <= n; i = i + 1) {
1261    if(diff(f, var(i)) != 0) { nrV++; index[nrV] = i; }
1262  }
1263  return(index);
1264}
1265
1266///////////////////////////////////////////////////////////////////////////////
1267
1268proc containedQ(def data,def f, list #)
1269"USAGE:    containedQ(data, f [, opt]); data=list; f=any type; opt=integer
1270PURPOSE:  test if f is an element of data.
1271RETURN:   int
1272          0 if f not contained in data
1273          1 if f contained in data
1274OPTIONS:  opt = 0 : use '==' for comparing f with elements from data@*
1275          opt = 1 : use @code{sameQ} for comparing f with elements from data
1276"
1277{
1278  int opt, i, found;
1279  if(size(#) > 0) { opt = #[1];}
1280  else { opt = 0; }
1281  i = 1;
1282  found = 0;
1283
1284  while((!found) && (i <= size(data))) {
1285    if(opt == 0) {
1286      if(f == data[i]) { found = 1;}
1287      else {i = i + 1;}
1288    }
1289    else {
1290      if(sameQ(f, data[i])) { found = 1;}
1291      else {i = i + 1;}
1292    }
1293  }
1294  return(found);
1295}
1296
1297//////////////////////////////////////////////////////////////////////////////
1298
1299proc sameQ(def a,def b)
1300"USAGE:    sameQ(a, b); a,b=list/intvec
1301PURPOSE:  test a == b elementwise, i.e., a[i] = b[i].
1302RETURN:   int
1303          0 if a != b
1304          1 if a == b
1305"
1306{
1307  if(typeof(a) == typeof(b)) {
1308    if(typeof(a) == "list" || typeof(a) == "intvec") {
1309      if(size(a) == size(b)) {
1310        int i = 1;
1311        int ok = 1;
1312        while(ok && (i <= size(a))) {
1313          if(a[i] == b[i]) { i = i + 1;}
1314          else {ok = 0;}
1315        }
1316        return(ok);
1317      }
1318      else { return(0); }
1319    }
1320    else { return(a == b);}
1321  }
1322  else { return(0);}
1323}
1324
1325///////////////////////////////////////////////////////////////////////////////
1326
1327static proc SimplifyPoly(poly f)
1328"USAGE:   SimplifyPoly(f); poly f
1329PURPOSE: reduces the coefficients of f w.r.t. the ideal 'moly' if they contain
1330         the algebraic number 'a'.
1331RETURN:  poly
1332ASSUME:  basering = Q[x_1,...,x_n,a]
1333         ideal mpoly must be defined, it might be 0 !
1334NOTE: outdated, use reduce instead
1335"
1336{
1337  matrix coMx;
1338  poly f1, vp;
1339
1340  vp = 1;
1341  for(int i = 1; i < nvars(basering); i++) { vp = vp * var(i);}
1342
1343  coMx = coef(f, vp);
1344  f1 = 0;
1345  for(i = 1; i <= ncols(coMx); i++) {
1346    f1 = f1 + coMx[1, i] * reduce(coMx[2, i], mpoly);
1347  }
1348  return(f1);
1349}
1350
1351///////////////////////////////////////////////////////////////////////////////
1352
1353static proc SimplifyData(def data)
1354"USAGE:   SimplifyData(data); ideal/list data;
1355PURPOSE: reduces the entries of 'data' w.r.t. the ideal 'mpoly' if they contain
1356         the algebraic number 'a'
1357RETURN:  ideal/list
1358ASSUME:  basering = Q[x_1,...,x_n,a]
1359         ideal 'mpoly' must be defined, it might be 0 !
1360"
1361{
1362  def altring=basering;
1363  int n;
1364  poly f;
1365
1366  if(typeof(data) == "ideal") { n = ncols(data); }
1367  else { n = size(data);}
1368
1369  for(int i = 1; i <= n; i++) {
1370    f = data[i];
1371    data[i] = SimplifyPoly(f);
1372  }
1373  return(data);
1374}
1375
1376///////////////////////////////////////////////////////////////////////////////
1377
1378static proc TransferRing(def R)
1379"USAGE:   TransferRing(R);
1380PURPOSE: creates a new ring containing the same variables as R, but without
1381         parameters. If R contains a parameter then this parameter is added
1382         as the last variable and 'minpoly' is represented by the ideal 'mpoly'
1383         If the basering does not contain a parameter then 'a' is added and
1384         'mpoly' = 0.
1385RETURN:  ring
1386ASSUME:  R = K[x_1,...,x_n] where K = Q or K = Q(a).
1387NOTE:    Creates the ring needed for all prodecures with name 'proc-name'Main
1388"
1389{
1390  def altring=basering;
1391  string ringSTR, parName, minPoly;
1392
1393  setring(R);
1394
1395  if(npars(basering) == 0) {
1396    parName = "a";
1397    minPoly = "0";
1398  }
1399  else {
1400    parName = parstr(basering);
1401    minPoly = string(minpoly);
1402  }
1403  ring TR = create_ring(0, "(" + varstr(basering) + "," + parName + ")", "lp");
1404  execute("ideal mpoly = std(" + minPoly + ");");
1405  export(mpoly);
1406  setring altring;
1407  return(TR);
1408}
1409
1410///////////////////////////////////////////////////////////////////////////////
1411
1412static proc NewBaseRing()
1413"USAGE:   NewBaseRing();
1414PURPOSE: creates a new ring, the last variable is added as a parameter.
1415         minpoly is set to mpoly[1].
1416RETURN:  ring
1417ASSUME:  basering = Q[x_1,...,x_n, a], 'mpoly' must be defined
1418"
1419{
1420  int n = nvars(basering);
1421  int MP;
1422  string ringSTR, parName, varString;
1423
1424  def BR = basering;
1425  if(mpoly[1] != 0) {
1426    parName = "(0, " + string(var(n)) + ")";
1427    MP = 1;
1428  }
1429  else {
1430    parName = "0";
1431    MP = 0;
1432  }
1433
1434
1435  for(int i = 1; i < n - 1; i++) {
1436    varString = varString + string(var(i)) + ",";
1437  }
1438  varString = varString + string(var(n-1));
1439
1440  ring TR = create_ring(parName, "(" + varString + ")", "lp");
1441  if(MP) { minpoly = number(imap(BR, mpoly)[1]); }
1442  setring BR;
1443  return(TR);
1444}
1445
1446///////////////////////////////////////////////////////////////////////////////
1447
1448/*
1449                           Examples:
1450
1451
1452// order = 20;
1453ring S1 = 0, (s(1..3)), lp;
1454ideal 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);
1455ideal mpoly = std(0);
1456
1457// order = 10
1458ring S2 = 0, (s(1..5)), lp;
1459ideal 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;
1460ideal mpoly = std(0);
1461
1462//order = 126
1463ring S3 =  0, (s(1..5)), lp;
1464ideal 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;
1465ideal mpoly = std(0);
1466
1467// order = 192
1468ring S4 = 0, (s(1..4)), lp;
1469ideal 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;
1470ideal mpoly = std(0);
1471
1472ring R = (0,a), (x,y,z), lp;
1473minpoly = a2 + 1;
1474ideal I1 = x2 - 1/2, a*z - 1, y - 2;
1475ideal I2 = x3 - 1/2, a*z2 - 3, y - 2*a;
1476
1477*/
Note: See TracBrowser for help on using the repository browser.