source: git/factory/cfCharSets.cc @ 9a8309

spielwiese
Last change on this file since 9a8309 was 9a8309, checked in by Martin Lee <martinlee84@…>, 10 years ago
chg: only use the squarefree parts when computing charsets
  • Property mode set to 100644
File size: 36.2 KB
Line 
1/*****************************************************************************\
2 * Computer Algebra System SINGULAR
3\*****************************************************************************/
4/** @file cfCharSets.cc
5 *
6 * This file provides functions to compute characteristic sets
7 *
8 * ABSTRACT: Descriptions can be found in Wang "On the Parallelization of
9 * characteristic-set based algorithms" or Greuel/Pfister "A Singular
10 * Introduction to Commutative Algebra".
11 *
12 * @authors Martin Lee, Michael Messollen
13 *
14 **/
15/*****************************************************************************/
16
17#include "timing.h"
18
19#include "cfCharSets.h"
20#include "canonicalform.h"
21#include "cf_algorithm.h"
22#include "facAlgFunc.h"
23
24TIMING_DEFINE_PRINT(neworder_time)
25
26#define __ARRAY_INIT__ -1
27
28// the maximal degree of polys in PS wrt. variable x
29static int
30degpsmax (const CFList & PS, const Variable & x,
31          Intarray & A, Intarray & C)
32{
33  int varlevel= level(x);
34  if (A[varlevel] != __ARRAY_INIT__)
35    return A[varlevel];
36  int max= 0, temp, count= 0;
37 
38  for (CFListIterator i= PS; i.hasItem(); i++)
39  {
40    temp= degree (i.getItem(), x);
41    if (temp > max) 
42    {
43      max= temp;
44      count = 0;
45    }
46    if (temp == max)
47      count += max;  // we count the number of polys
48  }
49  A[varlevel]= max;
50  C[varlevel]= count;
51  return max;
52}
53
54// the minimal non-zero degree of polys in PS wrt. x
55// returns 0 if variable x doesn't occure in any of the polys
56static int
57degpsmin (const CFList & PS, const Variable & x, Intarray & A, Intarray & B,
58          Intarray & C, Intarray & D)
59{
60  int varlevel= level(x);
61  if (B[varlevel] != __ARRAY_INIT__ )
62    return B[varlevel];
63  int min= degpsmax (PS, x, A, C), temp, count= 0;
64
65  if (min == 0)
66  {
67    B[varlevel]= min;
68    D[varlevel]= min;
69    return min;
70  }
71  else
72  {
73    for (CFListIterator i= PS; i.hasItem(); i++)
74    {
75      temp= degree (i.getItem(), x);
76      if (temp < min && temp != 0)
77      {
78        min= temp;
79        count= 0;
80      }
81      if (temp == min)
82        count += min; // we count the number of polys
83    }
84  }
85  B[varlevel]= min;
86  D[varlevel]= count;
87  return min;
88}
89
90// the minimal total degree of lcoeffs of polys in PS wrt. x
91// for those polys having degree degpsmin in x.
92// F will be assigned the minimal number of terms of those lcoeffs
93static int
94Tdeg (const CFList & PS, const Variable & x, Intarray & A, Intarray & B,
95      Intarray & C, Intarray & D, Intarray & E, Intarray & F)
96{
97  int k= degpsmin (PS, x, A, B, C, D), varlevel= level(x), min= 0;
98
99  if (E[varlevel] != __ARRAY_INIT__)
100    return E [varlevel];
101  if (k == 0)
102  {
103    E[varlevel]= 0;
104    F[varlevel]= 0;
105  }
106  else
107  {
108    int nopslc= 0;
109    CFList LCdegList;
110    CanonicalForm elem;
111    CFListIterator i;
112
113    for (i= PS; i.hasItem(); i++)
114    {
115      elem= i.getItem();
116      if (degree (elem, x) == k)
117        LCdegList.append (LC (elem, x));
118    }
119   
120    if (LCdegList.length() > 0)
121    {
122      CFList TermList;
123      int newmin, newnopslc;
124
125      min= totaldegree (LCdegList.getFirst());
126      TermList= get_Terms (LCdegList.getFirst()); 
127      nopslc= TermList.length();
128      for (i= LCdegList; i.hasItem(); i++)
129      {
130        elem= i.getItem();
131        newmin= totaldegree(elem);
132        TermList= get_Terms(elem);
133        newnopslc= TermList.length();
134        if (newmin < min)
135          min= newmin; 
136        if (newnopslc < nopslc)
137          nopslc= newnopslc;
138      }
139     
140    }
141    E[varlevel]= min;
142    F[varlevel]= nopslc;
143  }
144  return min;
145}
146
147// The number of the poly in which Variable x first occures
148static int
149nr_of_poly( const CFList & PS, const Variable & x, Intarray & G)
150{
151  int min= 0, varlevel= level(x);
152  if (G[varlevel] != __ARRAY_INIT__)
153    return G[varlevel];
154  for (CFListIterator i= PS; i.hasItem(); i++)
155  {
156    min += 1;
157    if (degree (i.getItem(), x) > 0)
158      break;
159  }
160  G[varlevel]= min;
161  return min;
162}
163
164static int
165degord (const Variable & x, const Variable & y, const CFList & PS,
166        Intarray & A, Intarray & B, Intarray & C, Intarray & D,
167        Intarray & E, Intarray & F, Intarray & G)
168{
169  int xlevel= level(x), ylevel= level(y);
170
171  if      (degpsmax(PS,y,A,C) < degpsmax(PS,x,A,C))         return 1;
172  else if (degpsmax(PS,x,A,C) < degpsmax(PS,y,A,C) )        return 0;
173  else if (C[ylevel] < C[xlevel])                           return 1;
174  else if (C[xlevel] < C[ylevel])                           return 0;
175  else if (degpsmin(PS,x,A,B,C,D) < degpsmin(PS,y,A,B,C,D)) return 1;
176  else if (degpsmin(PS,y,A,B,C,D) < degpsmin(PS,x,A,B,C,D)) return 0;
177  else if (D[ylevel] < D[xlevel])                           return 1;
178  else if (D[xlevel] < D[ylevel])                           return 0;
179  else if (Tdeg(PS,y,A,B,C,D,E,F) < Tdeg(PS,x,A,B,C,D,E,F)) return 1;
180  else if (Tdeg(PS,x,A,B,C,D,E,F) < Tdeg(PS,y,A,B,C,D,E,F)) return 0;
181  else if (F[ylevel] < F[xlevel])                           return 1;
182  else if (F[xlevel] < F[ylevel])                           return 0;
183  else if (nr_of_poly(PS,x,G) <= nr_of_poly(PS,y,G))        return 1;
184  else return 0;
185}
186
187// determine the highest variable of all involved Variables in PS
188// NOTE:
189//    this doesn't give always the correct answer:
190//    If a variable is assigned the highest level in the definition of the
191//    original ring, but doesn't occure in any of the
192//    polynomials, get_max_var returns the variable with a level lower than
193//    the highest level.
194//    Is there a workaround?
195// But for the redefinition of the ring this doesn't matter due to the
196// implementation of neworder().
197
198static Variable
199get_max_var(const CFList & PS)
200{
201  Variable x= PS.getFirst().mvar(), y;
202  for (CFListIterator i= PS; i.hasItem(); i++)
203  {
204    y= i.getItem().mvar();
205    if (y > x)
206      x= y;
207  }
208  return x;
209}
210
211
212// determine if variable x is in one and only one of the polynomials in PS
213// first criterion for neworder
214static CFList
215only_in_one (const CFList & PS, const Variable & x)
216{
217  CFList output;
218
219  for (CFListIterator i= PS; i.hasItem(); i++ )
220  {
221    if (degree (i.getItem(), x) >= 1)
222      output.insert (i.getItem());
223    if (output.length() >= 2)
224      break;
225  }
226  return output;
227}
228
229// initialize all Arrays (of same range) with __ARRAY_INIT__
230static void
231initArray (const int highest_level, Intarray & A, Intarray & B, Intarray & C,
232           Intarray & D, Intarray & E, Intarray & F, Intarray & G)
233{
234  for (int i=1 ; i <= highest_level; i ++)
235  {
236    A[i]= __ARRAY_INIT__;
237    B[i]= __ARRAY_INIT__;
238    C[i]= __ARRAY_INIT__;
239    D[i]= __ARRAY_INIT__;
240    E[i]= __ARRAY_INIT__;
241    F[i]= __ARRAY_INIT__;
242    G[i]= __ARRAY_INIT__;
243  }
244}
245
246// now for the second criterion; a little more complex
247//
248// idea: set up seven arrays of lenth highest_level
249//       (of which some entries may be empty, because of only_in_one!)
250//   A saves maxdegree of Variable x in A(level(x))
251//   B saves mindegree of Variable x in B(level(x))
252//   C saves the number of polys in PS which have degree A(level(x)) in
253//     D(level(x))
254//   D saves the number of polys in PS which have degree B(level(x)) in
255//     D(level(x))
256//   E saves the minimal total degree of lcoeffs of polys wrt x in E(level(x))
257//   F saves the minimal number of terms of lcoeffs of E(level(x)) in F(~)
258//   G saves nr of poly Variable x has first deg <> 0
259
260#define __INIT_GAP__ 3
261static Varlist
262reorderb (const Varlist & difference, const CFList & PS,
263          const int highest_level)
264{
265  Intarray A(1, highest_level), B(1, highest_level), C(1, highest_level),
266           D(1, highest_level), E(1, highest_level), F(1, highest_level),
267           G(1, highest_level);
268  initArray (highest_level, A, B, C, D, E, F, G);
269  int i= 0, j, n= difference.length(), gap= 1 + __INIT_GAP__;
270  Variable temp;
271  Array<Variable> v(0, n);
272  VarlistIterator J;
273
274  for (J= difference; J.hasItem(); J++ )
275  {
276    v[i]= J.getItem();
277    i++;
278  }
279 
280  while (gap <= n)
281    gap = __INIT_GAP__ * gap + 1;
282  gap /= __INIT_GAP__;
283 
284  while (gap > 0)
285  {
286    for (i= gap; i <= n - 1; i++)
287    {
288      temp= v[i];
289      for (j= i - gap; j >=0 ; j -= gap)
290      {
291        if (degord (v[j], temp, PS, A, B, C, D, E, F, G))
292          break;
293        v[j + gap]= v[j];
294      }
295      v[j + gap]= temp;
296    }
297    gap /= __INIT_GAP__;
298  }
299  Varlist output;
300  for (i= 0; i <= n - 1; i++)
301    output.append (v[i]);
302  return output;
303}
304
305// set up a new orderd list of Variables.
306// we try to reorder the variables heuristically optimal.
307Varlist
308neworder( const CFList & PolyList )
309{
310  CFList PS= PolyList, PS1=PolyList;
311  Varlist oldorder, reorder, difference;
312
313  TIMING_START(neworder_time);
314
315  int highest_level= level(get_max_var(PS));
316
317  // set up oldorder and first criterion: only_in_one
318  for (int i= highest_level; i>=1; i--)
319  {
320    oldorder.insert (Variable(i));
321    CFList is_one= only_in_one (PS1, Variable(i)); 
322    if (is_one.length() == 1)
323    {
324      reorder.insert (Variable(i));
325      PS1= Difference (PS1, is_one);
326    }
327    else if (is_one.length() == 0)
328    {
329      reorder.append (Variable (i)); // assigne it the highest level
330      PS1= Difference (PS1, is_one); 
331    }
332  }
333  difference= Difference (oldorder, reorder);
334
335  // rearrange the ordering of the variables!
336  difference= reorderb (difference, PS, highest_level);
337  reorder= Union (reorder, difference);
338  TIMING_END(neworder_time);
339
340  TIMING_PRINT(neworder_time, "\ntime used for neworder   : ");
341
342  return Union (reorder, Difference (oldorder, reorder));
343}
344
345// the same as above, only returning a list of CanonicalForms
346CFList
347newordercf(const CFList & PolyList )
348{
349  Varlist reorder= neworder (PolyList);
350  CFList output;
351
352  for (VarlistIterator i=reorder; i.hasItem(); i++)
353    output.append (CanonicalForm (i.getItem()));
354
355  return output;
356}
357
358// the same as above, only returning a list of ints
359IntList
360neworderint(const CFList & PolyList )
361{
362  Varlist reorder= neworder (PolyList);
363  IntList output;
364
365  for (VarlistIterator i= reorder; i.hasItem(); i++)
366    output.append (level (i.getItem()));
367
368  return output;
369}
370
371// swapvar a whole list of CanonicalForms
372static CFList
373swapvar( const CFList & PS, const Variable & x, const Variable & y)
374{
375  CFList ps;
376
377  for (CFListIterator i = PS; i.hasItem(); i++)
378    ps.append (swapvar (i.getItem(), x, y));
379  return ps;
380}
381
382static CFFList
383swapvar( const CFFList & PS, const Variable & x, const Variable & y)
384{
385  CFFList ps;
386
387  for (CFFListIterator i= PS; i.hasItem(); i++)
388    ps.append (CFFactor(swapvar (i.getItem().factor(), x, y), i.getItem().exp()));
389  return ps;
390}
391
392// a library function: we reorganize the global variable ordering
393CFList
394reorder (const Varlist & betterorder, const CFList & PS)
395{
396  int i= 1, n= betterorder.length();
397  Intarray v (1, n);
398  CFList ps= PS;
399
400  //initalize:
401  for (VarlistIterator j= betterorder; j.hasItem(); j++)
402  {
403    v[i]= level (j.getItem());
404    i++;
405  }
406  // reorder:
407  for (i= 1; i <= n; i++)
408    ps= swapvar (ps, Variable (v[i]), Variable (n + i));
409  return ps;
410}
411
412CFFList
413reorder( const Varlist & betterorder, const CFFList & PS)
414{
415  int i= 1, n= betterorder.length();
416  Intarray v (1, n);
417  CFFList ps= PS;
418
419  //initalize:
420  for (VarlistIterator j= betterorder; j.hasItem(); j++)
421  {
422    v[i]= level (j.getItem());
423    i++;
424  }
425
426  // reorder:
427  for (i= 1; i <= n; i++)
428    ps= swapvar (ps, Variable (v[i]), Variable (n + i));
429  return ps;
430}
431
432ListCFList
433reorder (const Varlist & betterorder, const ListCFList & Q)
434{
435  ListCFList Q1;
436
437  for (ListCFListIterator i= Q; i.hasItem(); i++)
438    Q1.append (reorder (betterorder, i.getItem()));
439  return Q1;
440}
441
442static bool
443lowerRank (const CanonicalForm & F, const CanonicalForm & G, int & ind)
444{
445  int degF, degG, levelF, levelG;
446
447  levelF= F.level();
448  levelG= G.level();
449  if (F.inCoeffDomain())
450  {
451    if (G.inCoeffDomain())
452      ind= 1;
453    return true;
454  }
455  else if (G.inCoeffDomain())
456    return false;
457  else if (levelF < levelG)
458    return true;
459  else if (levelF == levelG)
460  {
461    degF= degree(F);
462    degG= degree(G);
463    if (degF < degG)
464      return true;
465    else if (degF == degG)
466      return lowerRank (LC (F), LC (G), ind);
467    else
468      return false;
469  }
470  return false;
471}
472
473static
474CanonicalForm
475lowestRank (const CFList & L)
476{
477  CFListIterator i= L;
478  CanonicalForm f;
479  int ind= 0;
480  if (!i.hasItem())
481    return f;
482
483  f= i.getItem();
484  i++;
485
486  while (i.hasItem())
487  {
488    if (lowerRank (i.getItem(), f, ind))
489    {
490      if (ind)
491      {
492        if (size (i.getItem()) < size (f))
493          f= i.getItem();
494        ind= 0;
495      }
496      else
497        f= i.getItem();
498    }
499    i++;
500  }
501  return f;
502}
503
504CFList initials (const CFList& L)
505{
506  CFList result;
507  for (CFListIterator iter= L; iter.hasItem(); iter++)
508  {
509    if (!LC(iter.getItem()).inCoeffDomain())
510      result.append (LC (iter.getItem()));
511  }
512  return result;
513}
514
515// sort in descending order of length of elements
516void
517sortListCFList (ListCFList& list)
518{
519  int l= 1;
520  int k= 1;
521  CFList buf;
522  ListCFListIterator m;
523  for (ListCFListIterator i= list; l <= list.length(); i++, l++)
524  {
525    for (ListCFListIterator j= list; k <= list.length() - l; k++)
526    {
527      m= j;
528      m++;
529      if (j.getItem().length() < m.getItem().length())
530      {
531        buf= m.getItem();
532        m.getItem()= j.getItem();
533        j.getItem()= buf;
534        j++;
535        j.getItem()= m.getItem();
536      }
537      else
538        j++;
539    }
540    k= 1;
541  }
542}
543
544
545// sort in descending order of level of elements
546void
547sortCFListByLevel (CFList& list)
548{
549  int l= 1;
550  int k= 1;
551  CanonicalForm buf;
552  CFListIterator m;
553  for (CFListIterator i= list; l <= list.length(); i++, l++)
554  {
555    for (CFListIterator j= list; k <= list.length() - l; k++)
556    {
557      m= j;
558      m++;
559      if ((size (j.getItem()) < size (m.getItem())) ||
560          ((size (j.getItem()) == size (m.getItem()))
561            && (j.getItem().level() < m.getItem().level())))
562      {
563        buf= m.getItem();
564        m.getItem()= j.getItem();
565        j.getItem()= buf;
566        j++;
567        j.getItem()= m.getItem();
568      }
569      else
570        j++;
571    }
572    k= 1;
573  }
574}
575
576static bool
577member (const CanonicalForm& f, const CFList& F)
578{
579  for (CFListIterator i= F; i.hasItem(); i++)
580  {
581    if (i.getItem().mapinto() == f.mapinto())
582      return 1;
583  }
584  return 0;
585}
586
587// are list A and B the same?
588static bool
589same (const CFList& A, const CFList& B)
590{
591  if (A.length() != B.length())
592    return 0;
593
594  CFListIterator i;
595
596  for (i= A; i.hasItem(); i++)
597  {
598    if (!member (i.getItem(), B))
599      return 0;
600  }
601  for (i= B; i.hasItem(); i++)
602  {
603    if (!member (i.getItem(), A))
604      return 0;
605  }
606  return 1;
607}
608
609
610// is List cs contained in List of lists pi?
611static bool
612member (const CFList& cs, const ListCFList& pi)
613{
614  if (pi.isEmpty())
615    return 0;
616
617  ListCFListIterator i;
618
619  for (i= pi; i.hasItem(); i++)
620  {
621    if (i.getItem().length() != cs.length())
622      continue;
623    if (same (cs, i.getItem()))
624      return 1;
625  }
626  return 0;
627}
628
629// is PS a subset of Cset ?
630static bool
631subset (const CFList &PS, const CFList& Cset)
632{
633  for (CFListIterator i= PS; i.hasItem(); i++)
634  {
635    if (!member (i.getItem(), Cset))
636      return 0;
637  }
638  return 1;
639}
640
641// Union of two List of Lists
642static ListCFList
643MyUnion (const ListCFList& a, const ListCFList& b)
644{
645  if (a.isEmpty())
646    return b;
647  if (b.isEmpty())
648    return a;
649
650  ListCFList output;
651  ListCFListIterator i;
652  CFList elem;
653
654  for (i= a; i.hasItem(); i++)
655  {
656    elem= i.getItem();
657    if ((!elem.isEmpty()) && (!member (elem, output)))
658      output.append(elem);
659  }
660
661  for (i= b; i.hasItem(); i++)
662  {
663    elem= i.getItem();
664    if ((!elem.isEmpty()) && (!member (elem, output)))
665      output.append(elem);
666  }
667  return output;
668}
669
670// Union of a and b stored in b
671void
672MyUnion2 (const ListCFList& a, ListCFList& b)
673{
674  if (a.isEmpty())
675    return;
676  if (b.isEmpty())
677  {
678    b= a;
679    return;
680  }
681
682  ListCFListIterator i;
683  CFList elem;
684
685  for (i= a; i.hasItem(); i++)
686  {
687    elem= i.getItem();
688    if ((!elem.isEmpty()) && (!member (elem, b)))
689      b.insert(elem);
690  }
691}
692
693//if list b is member of the list of lists remove b and return the rest
694static ListCFList
695MyDifference (const ListCFList& a, const CFList& b)
696{
697  ListCFList output;
698  ListCFListIterator i;
699  CFList elem;
700
701  for (i= a; i.hasItem(); i++)
702  {
703    elem= i.getItem();
704    if ((!elem.isEmpty()) && (!same (elem, b)))
705      output.append (elem);
706  }
707  return output;
708}
709
710// remove all elements of b from list of lists a and return the rest
711static ListCFList
712Minus( const ListCFList& a, const ListCFList& b)
713{
714  ListCFList output= a;
715
716  for (ListCFListIterator i=b; i.hasItem(); i++)
717    output = MyDifference (output, i.getItem());
718
719  return output;
720}
721
722static ListCFList
723adjoin (const CFList& is, const CFList& qs, const ListCFList& qh)
724{
725  ListCFList iss, qhi;
726  ListCFListIterator j;
727  CFList iscopy, itt;
728  CFListIterator i;
729  int ind, length;
730
731  for (i= is; i.hasItem(); i++)
732  {
733    if (i.getItem().level() > 0)
734      iscopy= Union (CFList (i.getItem()), iscopy);
735  }
736  if (iscopy.isEmpty())
737    return iss;
738
739  qhi= MyDifference (qh, qs);
740  length= qhi.length();
741
742  for (i= iscopy; i.hasItem(); i++)
743  {
744    itt= Union (qs, CFList (i.getItem()));
745    ind= 0;
746    if (length > 0)
747    {
748      for (j= qhi; j.hasItem(); j++)
749      {
750        if (subset (j.getItem(), itt))
751          ind= 1;
752      }
753    }
754    if (ind == 0)
755      iss.append (itt);
756  }
757  return iss;
758}
759
760static ListCFList
761adjoinb (const CFList & is, const CFList & qs, const ListCFList & qh ,const CFList & cs)
762{
763  ListCFList iss, qhi;
764  ListCFListIterator j;
765  CFList iscopy, itt;
766  CFListIterator i;
767  int ind, length;
768
769  for (i= is ; i.hasItem(); i++)
770  {
771    if (i.getItem().level() > 0)
772      iscopy= Union (CFList (i.getItem()), iscopy);
773  }
774  if (iscopy.isEmpty())
775    return iss;
776  qhi= MyDifference (qh, qs);
777  length= qhi.length();
778  for (i= iscopy; i.hasItem(); i++)
779  {
780    itt= Union (Union (qs, CFList (i.getItem())), cs);
781    ind= 0;
782    if (length > 0)
783    {
784      for (j= qhi; j.hasItem(); j++)
785      {
786        if (subset (j.getItem(), itt))
787          ind= 1;
788      }
789    }
790    if (ind == 0)
791      iss.append(itt);
792  }
793  return iss;
794}
795
796static void
797select (const ListCFList& ppi, int length, ListCFList& ppi1, ListCFList& ppi2)
798{
799  CFList elem;
800  for (ListCFListIterator i=ppi; i.hasItem(); i++)
801  {
802    elem = i.getItem();
803    if (!elem.isEmpty())
804    {
805      if (length <= elem.length())
806        ppi2.append(elem);
807      else
808        ppi1.append(elem);
809    }
810  }
811}
812
813CanonicalForm normalize (const CanonicalForm& F)
814{
815  if (F.isZero())
816    return F;
817  if (getCharacteristic() == 0)
818  {
819    CanonicalForm G;
820    bool isRat= isOn (SW_RATIONAL);
821    if (!isRat)
822      On (SW_RATIONAL);
823    G= F;
824    G *= bCommonDen (G);
825    if (!isRat)
826      Off (SW_RATIONAL);
827    if (isRat)
828      Off (SW_RATIONAL);
829    G= F/icontent (F);
830    if (isRat)
831      On (SW_RATIONAL);
832    return G;
833  }
834
835  return F/lc (F);
836}
837
838static
839CanonicalForm
840Prem (const CanonicalForm& F, const CanonicalForm& G)
841{
842  CanonicalForm f, g, l, test, lu, lv, t, retvalue;
843  int degF, degG, levelF, levelG;
844  bool reord;
845  Variable v, vg= G.mvar();
846
847  if ( (levelF= F.level()) < (levelG= G.level()))
848    return F;
849  else
850  {
851    if ( levelF == levelG )
852    {
853      f= F;
854      g= G;
855      reord= false;
856      v= F.mvar();
857    }
858    else
859    {
860      v= Variable (levelF + 1);
861      f= swapvar (F, vg, v);
862      g= swapvar (G, vg, v);
863      reord= true;
864    }
865    degG= degree (g, v );
866    degF= degree (f, v );
867    if (degG <= degF)
868    {
869      l= LC (g);
870      g= g - l*power (v, degG);
871    }
872    else
873      l= 1;
874    while ((degG <= degF) && (!f.isZero()))
875    {
876      test= gcd (l, LC(f));
877      lu= l / test;
878      lv= LC(f) / test;
879
880      t= power (v, degF - degG)*g*lv;
881
882      if (degF == 0)
883        f= 0;
884      else
885        f= f - LC (f)*power (v, degF);
886
887      f= lu*f - t;
888      degF= degree (f, v);
889    }
890
891    if (reord)
892      retvalue= swapvar (f, vg, v);
893    else
894      retvalue= f;
895
896    return retvalue;
897  }
898}
899
900static
901CanonicalForm
902Premb (const CanonicalForm &f, const CFList &L)
903{
904  CanonicalForm rem= f;
905  CFList l= L;
906  l.removeFirst();
907  CFListIterator i= l;
908
909  for (i.lastItem(); i.hasItem(); i--)
910    rem= normalize (Prem (rem, i.getItem()));
911
912  CanonicalForm tmp= L.getFirst()/content (L.getFirst());
913
914  bool isRat= isOn (SW_RATIONAL);
915  if (getCharacteristic() == 0 && !isRat)
916    On (SW_RATIONAL);
917  if (fdivides (tmp, rem))
918  {
919    if (getCharacteristic() == 0 && !isRat)
920      Off (SW_RATIONAL);
921    return 0;
922  }
923
924  if (getCharacteristic() == 0 && !isRat)
925    Off (SW_RATIONAL);
926
927  rem= normalize (Prem (rem, L.getFirst()));
928
929  return rem;
930}
931
932static
933CanonicalForm
934Prem (const CanonicalForm &f, const CFList &L)
935{
936  CanonicalForm rem= f;
937  CFListIterator i= L;
938
939  for (i.lastItem(); i.hasItem(); i--)
940    rem= normalize (Prem (rem, i.getItem()));
941
942  return rem;
943}
944
945CFList uniGcd (const CFList& L)
946{
947  CFList tmp;
948  CanonicalForm g;
949  CFListIterator i;
950  for (i= L; i.hasItem(); i++)
951  {
952    if (i.getItem().isUnivariate() && i.getItem().level() == 1)
953      tmp.append (i.getItem());
954  }
955  if (tmp.length() <= 2)
956    return L;
957  i= tmp;
958  g= i.getItem();
959  i++;
960  g= gcd (g,i.getItem());
961  i++;
962  for (; i.hasItem(); i++)
963    g= gcd (g, i.getItem());
964  return Union (Difference (L, tmp), CFList (g));
965}
966
967
968CFList
969factorsOfInitials(const CFList & L)
970{
971  CFList result;
972  CFFList factors;
973  CanonicalForm tmp;
974
975  for (CFListIterator i= L; i.hasItem(); i++)
976  {
977    factors= factorize (LC (i.getItem()));
978    for (CFFListIterator j= factors; j.hasItem(); j++)
979    {
980      tmp= j.getItem().factor();
981      if (!tmp.inCoeffDomain())
982        result= Union (result, CFList (normalize (tmp)));
983    }
984  }
985
986  return result;
987}
988
989void
990removeContent (CanonicalForm& F, CanonicalForm& cF)
991{
992  if (size (F) == 1)
993  {
994    CanonicalForm tmp= F;
995    F= F.mvar();
996    cF= tmp/F;
997    if (!cF.inCoeffDomain())
998      cF= normalize (cF);
999    else
1000      cF= 0;
1001
1002    return;
1003  }
1004
1005  cF= content (F);
1006
1007  if (cF.inCoeffDomain())
1008    cF= 0;
1009  else
1010  {
1011    cF= normalize (cF);
1012    F /= cF;
1013    F= normalize (F);
1014  }
1015}
1016
1017CFList
1018factorPSet (const CFList& PS)
1019{
1020  CFList result;
1021  CFFList factors;
1022  CFFListIterator j;
1023
1024  for (CFListIterator i= PS; i. hasItem(); i++)
1025  {
1026    factors= factorize (i.getItem());
1027    if (factors.getFirst().factor().inCoeffDomain())
1028      factors.removeFirst();
1029    for (j= factors; j.hasItem(); j++ )
1030      result= Union (result, CFList (normalize (j.getItem().factor())));
1031  }
1032  return result;
1033}
1034
1035void
1036removeFactors (CanonicalForm& r, StoreFactors& StoredFactors,
1037               CFList& removedFactors)
1038{
1039  CanonicalForm quot;
1040  CFList testlist;
1041  int n= level(r);
1042  bool divides;
1043  CFListIterator j;
1044
1045  for (int i=1; i<= n; i++)
1046    testlist.append (CanonicalForm (Variable (i)));
1047
1048  for (j= StoredFactors.FS1; j.hasItem(); j++)
1049  {
1050    while (fdivides (j.getItem(), r, quot))
1051    {
1052      if (!quot.inCoeffDomain())
1053        r= quot;
1054      else
1055        break;
1056    }
1057  }
1058
1059  // remove already removed factors
1060  for (j= StoredFactors.FS2; j.hasItem(); j++)
1061  {
1062    divides= false;
1063    while (fdivides (j.getItem(), r, quot))
1064    {
1065      if (!quot.inCoeffDomain())
1066      {
1067        divides= true;
1068        r= quot;
1069      }
1070      else
1071        break;
1072    }
1073    if (divides)
1074      removedFactors= Union (removedFactors, CFList (j.getItem()));
1075  }
1076  r= normalize (r);
1077
1078  // remove variables
1079  for (j= testlist; j.hasItem() && !r.isOne(); j++)
1080  {
1081    while (fdivides (j.getItem(), r, quot))
1082    {
1083      if (!quot.inCoeffDomain())
1084        r= quot;
1085      else
1086        break;
1087      removedFactors= Union (removedFactors, CFList (j.getItem()));
1088    }
1089  }
1090}
1091
1092CFList
1093removeContent (const CFList & PS, StoreFactors & StoredFactors)
1094{
1095  CFListIterator i= PS;
1096  if ((!i.hasItem()) || (PS.getFirst().level() == 0 ))
1097    return PS;
1098
1099  CFList output;
1100  CanonicalForm cc,elem;
1101
1102  for (; i.hasItem(); i++)
1103  {
1104    elem= i.getItem();
1105    cc= content (elem, elem.mvar());
1106    if (cc.level() > 0 )
1107    {
1108      output.append (elem / cc);
1109      StoredFactors.FS1 = Union (CFList (cc), StoredFactors.FS1);
1110    }
1111    else
1112      output.append(elem);
1113  }
1114  return output;
1115}
1116
1117static bool
1118contractsub (const CFList& cs1, const CFList& cs2)
1119{
1120  CFListIterator i;
1121
1122  CanonicalForm r;
1123  for (i= cs1; i.hasItem(); i++)
1124  {
1125    if (Prem (i.getItem(), cs2) != 0)
1126      return false;
1127  }
1128
1129  CFList is= factorsOfInitials (cs1);
1130
1131  for (i= is; i.hasItem(); i++)
1132  {
1133    if (Prem (i.getItem(), cs2) == 0)
1134      return false;
1135  }
1136  return true;
1137}
1138
1139static ListCFList
1140contract (const ListCFList& cs)
1141{
1142  ListCFList mem, ts;
1143  CFList iitem, jitem;
1144
1145  if (cs.length() < 2)
1146    return cs;
1147
1148  int l= cs.length();
1149  int ii= 1;
1150  ListCFListIterator j;
1151  for (ListCFListIterator i= cs; i.hasItem() && ii < l; i++, ii++)
1152  {
1153    iitem= i.getItem();
1154    if (!member (iitem, mem))
1155    {
1156      j= i;
1157      j++;
1158      for (; j.hasItem(); j++)
1159      {
1160        jitem= j.getItem();
1161        if (!member (jitem, mem))
1162        {
1163          if (contractsub (iitem, jitem))
1164          {
1165            ts.append (jitem);
1166            mem.append (jitem);
1167          }
1168          else
1169          {
1170            if (contractsub (jitem, iitem))
1171              ts.append (iitem); // no mem.append (item) because we assume cs does not contain duplicate entries
1172          }
1173        }
1174      }
1175    }
1176  }
1177  return Minus (cs,ts);
1178}
1179
1180
1181CFList
1182basicSet (const CFList &PS)
1183{
1184  CFList QS= PS, BS, RS;
1185  CanonicalForm b;
1186  int cb, degb;
1187
1188  if (PS.length() < 2)
1189    return PS;
1190
1191  CFListIterator i;
1192
1193  while (!QS.isEmpty())
1194  {
1195    b= lowestRank (QS);
1196    cb= b.level();
1197
1198    BS= Union(CFList (b), BS);
1199
1200    if (cb <= 0)
1201      return CFList();
1202    else
1203    {
1204      degb= degree (b);
1205      RS= CFList();
1206      for (i= QS; i.hasItem(); i++)
1207      {
1208        if (degree (i.getItem(), cb) < degb)
1209          RS= Union (CFList (i.getItem()), RS);
1210      }
1211      QS= RS;
1212    }
1213  }
1214
1215  return BS;
1216}
1217
1218CFList
1219charSet (const CFList &PS)
1220{
1221  CFList QS= PS, RS= PS, CSet, tmp;
1222  CFListIterator i;
1223  CanonicalForm r;
1224
1225  while (!RS.isEmpty())
1226  {
1227    CSet= basicSet (QS);
1228
1229    RS= CFList();
1230    if (CSet.length() > 0 && CSet.getFirst().level() > 0)
1231    {
1232      tmp= Difference (QS, CSet);
1233      for (i= tmp; i.hasItem(); i++)
1234      {
1235        r= Prem (i.getItem(), CSet);
1236        if (r != 0)
1237          RS= Union (RS, CFList (r));
1238      }
1239      QS= Union (QS, RS);
1240    }
1241  }
1242
1243  return CSet;
1244}
1245
1246/// medial set
1247CFList
1248charSetN (const CFList &PS)
1249{
1250  CFList QS= PS, RS= PS, CSet, tmp;
1251  CFListIterator i;
1252  CanonicalForm r;
1253
1254  while (!RS.isEmpty())
1255  {
1256    QS= uniGcd (QS);
1257    CSet= basicSet (QS);
1258
1259    RS= CFList();
1260    if (CSet.length() > 0 && CSet.getFirst().level() > 0)
1261    {
1262      tmp= Difference (QS, CSet);
1263      for (i= tmp; i.hasItem(); i++)
1264      {
1265        r= Prem (i.getItem(), CSet);
1266        if (!r.isZero())
1267          RS= Union (RS, CFList (r));
1268      }
1269      QS= Union (CSet, RS);
1270    }
1271  }
1272
1273  return CSet;
1274}
1275
1276/// compute a characteristic set via medial set
1277CFList
1278charSetViaCharSetN (const CFList& PS)
1279{
1280  CFList L;
1281  CFFList sqrfFactors;
1282  CanonicalForm sqrf;
1283  CFFListIterator iter2;
1284  for (CFListIterator iter= PS; iter.hasItem(); iter++)
1285  {
1286    sqrf= 1;
1287    sqrfFactors= sqrFree (iter.getItem());
1288    for (iter2= sqrfFactors; iter2.hasItem(); iter2++)
1289      sqrf *= iter2.getItem().factor();
1290    L= Union (L, CFList (normalize (sqrf)));
1291  }
1292
1293  CFList result= charSetN (L);
1294
1295  if (result.isEmpty() || result.getFirst().inCoeffDomain())
1296    return CFList(1);
1297
1298  CanonicalForm r;
1299  CFList RS;
1300  CFList tmp= Difference (L, result);
1301
1302  for (CFListIterator i= tmp; i.hasItem(); i++)
1303  {
1304    r= Premb (i.getItem(), result);
1305    if (!r.isZero())
1306      RS= Union (RS, CFList (r));
1307  }
1308  if (RS.isEmpty())
1309    return result;
1310
1311  return charSetViaCharSetN (Union (L, Union (RS, result)));
1312}
1313
1314/// modified medial set
1315CFList
1316modCharSet (const CFList& L, StoreFactors& StoredFactors, bool removeContents)
1317{
1318  CFList QS= L, RS= L, CSet, tmp, contents, initial, removedFactors;
1319  CFListIterator i;
1320  CanonicalForm r, cF;
1321  bool noRemainder= true;
1322  StoreFactors StoredFactors2;
1323
1324  QS= uniGcd (L);
1325
1326  while (!RS.isEmpty())
1327  {
1328    noRemainder= true;
1329    CSet= basicSet (QS);
1330
1331    initial= factorsOfInitials (CSet);
1332
1333    StoredFactors2.FS1= StoredFactors.FS1;
1334    StoredFactors2.FS2= Union (StoredFactors2.FS2, initial);
1335
1336    RS= CFList();
1337
1338    if (CSet.length() > 0 && CSet.getFirst().level() > 0)
1339    {
1340      tmp= Difference (QS, CSet);
1341
1342      for (i= tmp; i.hasItem(); i++)
1343      {
1344        r= Prem (i.getItem(), CSet);
1345        if (!r.isZero())
1346        {
1347          noRemainder= false;
1348          if (removeContents)
1349          {
1350            removeContent (r, cF);
1351
1352            if (!cF.isZero())
1353              contents= Union (contents, factorPSet (CFList(cF))); //factorPSet maybe too much it should suffice to do a squarefree factorization instead
1354          }
1355
1356          removeFactors (r, StoredFactors2, removedFactors);
1357          StoredFactors2.FS1= Union (StoredFactors2.FS1, removedFactors);
1358          StoredFactors2.FS2= Difference (StoredFactors2.FS2, removedFactors);
1359
1360          removedFactors= CFList();
1361
1362          RS= Union (RS, CFList (r));
1363        }
1364      }
1365
1366      if (removeContents && !noRemainder)
1367      {
1368        StoredFactors.FS1= Union (StoredFactors2.FS1, contents);
1369        StoredFactors.FS2= StoredFactors2.FS2;
1370      }
1371      else
1372        StoredFactors= StoredFactors2;
1373
1374      QS= Union (CSet, RS);
1375
1376      contents= CFList();
1377      removedFactors= CFList();
1378    }
1379    else
1380      StoredFactors= StoredFactors2;
1381  }
1382
1383  return CSet;
1384}
1385
1386/// characteristic set via modified medial set
1387CFList
1388charSetViaModCharSet (const CFList& PS, StoreFactors& StoredFactors, bool removeContents)
1389{
1390  CFList L;
1391  CFFList sqrfFactors;
1392  CanonicalForm sqrf;
1393  CFFListIterator iter2;
1394  for (CFListIterator iter= PS; iter.hasItem(); iter++)
1395  {
1396    sqrf= 1;
1397    sqrfFactors= sqrFree (iter.getItem());
1398    for (iter2= sqrfFactors; iter2.hasItem(); iter2++)
1399      sqrf *= iter2.getItem().factor();
1400    L= Union (L, CFList (normalize (sqrf)));
1401  }
1402
1403  L= uniGcd (L);
1404
1405  CFList result= modCharSet (L, StoredFactors, removeContents);
1406
1407  if (result.isEmpty() || result.getFirst().inCoeffDomain())
1408    return CFList(1);
1409
1410  CanonicalForm r;
1411  CFList RS;
1412  CFList tmp= Difference (L, result);
1413
1414  for (CFListIterator i= tmp; i.hasItem(); i++)
1415  {
1416    r= Premb (i.getItem(), result);
1417    if (!r.isZero())
1418      RS= Union (RS, CFList (r));
1419  }
1420  if (RS.isEmpty())
1421    return result;
1422
1423  return charSetViaModCharSet (Union (L, Union (RS, result)), StoredFactors, removeContents);
1424}
1425
1426CFList
1427charSetViaModCharSet (const CFList& PS, bool removeContents)
1428{
1429  StoreFactors tmp;
1430  return charSetViaModCharSet (PS, tmp, removeContents);
1431}
1432
1433ListCFList
1434charSeries (const CFList& L)
1435{
1436  ListCFList tmp, result, tmp2, ppi1, ppi2, qqi, ppi, alreadyConsidered;
1437  CFList l, charset, ini;
1438
1439  int count= 0;
1440  int highestLevel= 1;
1441  CFListIterator iter;
1442
1443  StoreFactors StoredFactors;
1444
1445  l= L;
1446
1447  for (iter= l; iter.hasItem(); iter++)
1448  {
1449    iter.getItem()= normalize (iter.getItem());
1450    if (highestLevel < iter.getItem().level())
1451      highestLevel= iter.getItem().level();
1452  }
1453
1454  tmp= ListCFList (l);
1455
1456  while (!tmp.isEmpty())
1457  {
1458    sortListCFList (tmp);
1459
1460    l= tmp.getFirst();
1461
1462    tmp= MyDifference (tmp, l);
1463
1464    select (ppi, l.length(), ppi1, ppi2);
1465
1466    MyUnion2 (ppi2, qqi);
1467
1468    if (count > 0)
1469      ppi= MyUnion (ListCFList (l), ppi1);
1470    else
1471      ppi= ListCFList();
1472
1473    if (l.length() - 3 < highestLevel)
1474      charset= charSetViaModCharSet (l, StoredFactors);
1475    else
1476      charset= charSetViaCharSetN (l);
1477
1478    if (charset.length() > 0 && charset.getFirst().level() > 0)
1479    {
1480      result= MyUnion (result, ListCFList (charset));
1481      ini= factorsOfInitials (charset);
1482
1483      ini= Union (ini, factorPSet (StoredFactors.FS1));
1484      sortCFListByLevel (ini);
1485    }
1486    else
1487    {
1488      ini= factorPSet (StoredFactors.FS1);
1489      sortCFListByLevel (ini);
1490    }
1491
1492    tmp2= adjoin (ini, l, qqi);
1493    tmp= MyUnion (tmp, tmp2);
1494
1495    StoredFactors.FS1= CFList();
1496    StoredFactors.FS2= CFList();
1497
1498    ppi1= ListCFList();
1499    ppi2= ListCFList();
1500
1501    count++;
1502  }
1503
1504  //TODO need to remove superflous components
1505
1506  return result;
1507}
1508
1509static bool
1510irreducible (const CFList & AS)
1511{
1512// AS is given by AS = { A1, A2, .. Ar }, d_i = degree(Ai)
1513
1514// 1) we test: if d_i > 1, d_j =1 for all j<>i, then AS is irreducible.
1515  bool deg1= true;
1516  for (CFListIterator i= AS ; i.hasItem(); i++)
1517  {
1518    if (degree (i.getItem()) > 1)
1519    {
1520      if (deg1)
1521        deg1= false;
1522      else
1523        return false; // found 2nd poly with deg > 1
1524    }
1525  }
1526  return true;
1527}
1528
1529static CFList
1530irredAS (CFList & AS, int & indexRed, CanonicalForm & reducible)
1531{
1532  CFFList qs;
1533  CFList ts, as;
1534  CanonicalForm elem;
1535  bool ind= true;
1536  int nr= 0, success= -1;
1537  CFListIterator i;
1538
1539  indexRed= 0;
1540  for (i= AS; i.hasItem(); i++ )
1541  {
1542    nr += 1;
1543    if (degree (i.getItem()) > 1)
1544    {
1545      qs= factorize (i.getItem());
1546      if (qs.getFirst().factor().inCoeffDomain())
1547        qs.removeFirst();
1548    }
1549    else
1550      qs= CFFList (CFFactor (i.getItem(), 1));
1551
1552    if ((qs.length() >= 2 ) || (qs.getFirst().exp() > 1))
1553    {
1554      indexRed= nr;
1555      ind= false;
1556      reducible= i.getItem();
1557      break;
1558    }
1559  }
1560
1561  if (ind)
1562  {
1563    if (irreducible (AS))  // as quasilinear? => irreducible!
1564      indexRed= 0;
1565    else
1566    {
1567      i= AS;
1568      for (nr= 1; nr< AS.length(); nr++)
1569      {
1570        as.append (i.getItem());
1571        i++;
1572        if (degree (i.getItem()) > 1)
1573        {  // search for a non linear elem
1574          qs= newfactoras (i.getItem(), as, success);
1575          if (qs.getFirst().factor().inCoeffDomain())
1576            qs.removeFirst();
1577          if (qs.length() > 1 || qs.getFirst().exp() > 1)
1578          { //found elem is reducible
1579            reducible= i.getItem();
1580            indexRed= nr + 1;
1581            break;
1582          }
1583        }
1584      }
1585    }
1586  }
1587  for (CFFListIterator k= qs; k.hasItem(); k++)
1588    ts.append (k.getItem().factor());
1589  return ts;
1590}
1591
1592ListCFList
1593irrCharSeries (const CFList & PS)
1594{
1595  CanonicalForm reducible, reducible2;
1596  CFList qs, cs, factorset, is, ts, L;
1597  CanonicalForm sqrf;
1598  CFFList sqrfFactors;
1599  CFFListIterator iter2;
1600  for (CFListIterator iter= PS; iter.hasItem(); iter++)
1601  {
1602    sqrf= 1;
1603    sqrfFactors= sqrFree (iter.getItem());
1604    if (sqrfFactors.getFirst().factor().inCoeffDomain())
1605      sqrfFactors.removeFirst();
1606    for (iter2= sqrfFactors; iter2.hasItem(); iter2++)
1607      sqrf *= iter2.getItem().factor();
1608    sqrf= normalize (sqrf);
1609    L= Union (L, CFList (sqrf));
1610  }
1611
1612  ListCFList pi, ppi, qqi, qsi, iss, qhi= ListCFList(L);
1613
1614  int nr_of_iteration= 0, indexRed, highestlevel= 0;
1615
1616  for (CFListIterator iter= PS; iter.hasItem(); iter++)
1617  {
1618    if (level (iter.getItem()) > highestlevel)
1619      highestlevel= level(iter.getItem());
1620  }
1621
1622  while (!qhi.isEmpty())
1623  {
1624    sortListCFList (qhi);
1625
1626    qs= qhi.getFirst();
1627
1628    ListCFList ppi1,ppi2;
1629    select (ppi, qs.length(), ppi1, ppi2);
1630
1631    MyUnion2 (ppi2, qqi);
1632
1633    if (nr_of_iteration == 0)
1634    {
1635      nr_of_iteration += 1;
1636      ppi= ListCFList();
1637    }
1638    else
1639    {
1640      nr_of_iteration += 1;
1641      ppi= MyUnion (ListCFList(qs), ppi1);
1642    }
1643
1644    StoreFactors StoredFactors;
1645    cs= charSetViaModCharSet (qs, StoredFactors);
1646    cs= removeContent (cs, StoredFactors);
1647
1648    factorset= StoredFactors.FS1;
1649
1650    if (cs.getFirst().level() > 0)
1651    {
1652      ts= irredAS (cs, indexRed, reducible);
1653
1654      if (indexRed <= 0) // irreducible
1655      {
1656        if (!subset (cs,qs))
1657          cs= charSetViaCharSetN (Union (qs,cs));
1658        if (!member (cs, pi))
1659        {
1660          pi= MyUnion (pi, ListCFList (cs));
1661          if (cs.getFirst().level() > 0)
1662          {
1663            ts= irredAS (cs, indexRed, reducible);
1664
1665            if (indexRed <= 0) //irreducible
1666            {
1667              qsi= MyUnion (qsi, ListCFList(cs));
1668              if (cs.length() == highestlevel)
1669                is= factorPSet (factorset);
1670              else
1671                is= Union (factorsOfInitials (cs), factorPSet (factorset));
1672              iss= adjoin (is, qs, qqi);
1673            }
1674          }
1675          else
1676            iss= adjoin (factorPSet (factorset), qs, qqi);
1677        }
1678        else
1679          iss= adjoin (factorPSet (factorset), qs, qqi);
1680      }
1681
1682      if (indexRed > 0)
1683      {
1684        is= factorPSet (factorset);
1685        if (indexRed > 1)
1686        {
1687          CFList cst;
1688          for (CFListIterator i= cs ; i.hasItem(); i++)
1689          {
1690            if (i.getItem() == reducible)
1691              break;
1692            else 
1693              cst.append (i.getItem());
1694          }
1695          is= Union (factorsOfInitials (cst), is);
1696          iss= MyUnion (adjoin (is, qs, qqi), adjoinb (ts, qs, qqi, cst));
1697        }
1698        else
1699          iss= adjoin (Union (is, ts), qs, qqi);
1700      }
1701    }
1702    else
1703      iss= adjoin (factorPSet (factorset), qs, qqi);
1704    if (qhi.length() > 1)
1705    {
1706      qhi.removeFirst();
1707      qhi= MyUnion (qhi, iss);
1708    }
1709    else
1710      qhi= iss;
1711  }
1712  if (!qsi.isEmpty())
1713    return contract (qsi);
1714  return ListCFList() ;
1715}
1716
Note: See TracBrowser for help on using the repository browser.