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

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