source: git/Singular/LIB/ncfactor.lib @ d17cfd

fieker-DuValspielwiese
Last change on this file since d17cfd was f0e4975, checked in by Viktor Levandovskyy <levandov@…>, 14 years ago
*levandov: cleanup and minifixes git-svn-id: file:///usr/local/Singular/svn/trunk@13482 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100755
File size: 59.5 KB
Line 
1///////////////////////////////////////////////////////////
2version = "$Id$";
3category="Noncommutative";
4info="
5LIBRARY: ncfactor.lib  Tools for factorization in some noncommutative algebras
6AUTHORS: Albert Heinle,     albert.heinle@rwth-aachen.de
7@*       Viktor Levandovskyy,     levandov@math.rwth-aachen.de
8
9OVERVIEW: In this library, new methods for factorization on polynomials
10  are implemented for two algebras, both generated by two generators (Weyl and
11  shift algebras) over a field K. Recall, that   the first Weyl algebra over K
12  is generated by x,d obeying the relation d*x=x*d+1.
13@* The first shift algebra over K is generated by x,s obeying the relation s*x=x*s+s.
14@* More detailled description of the algorithms can be found at
15@url{http://www.math.rwth-aachen.de/\~Albert.Heinle}.
16
17Guide: We are interested in computing a tree of factorizations, that is at the moment
18a list of all found factorizations is returned. It may contain factorizations, which
19are further reducible.
20
21PROCEDURES:
22  facFirstWeyl(h);    factorization in the first Weyl algebra
23  testNCfac(l[,h]);   tests factorizations from a given list for correctness
24  facSubWeyl(h,X,D);  factorization in the first Weyl algebra as a subalgebra
25  facFirstShift(h);   factorization in the first shift algebra
26";
27
28LIB "general.lib";
29LIB "nctools.lib";
30LIB "involut.lib";
31LIB "freegb.lib"; // for isVar
32
33proc tst_ncfactor()
34{
35  example facFirstWeyl;
36  example facFirstShift;
37  example facSubWeyl;
38  example testNCfac;
39}
40
41/////////////////////////////////////////////////////
42//==================================================*
43//deletes double-entries in a list of factorization
44//without evaluating the product.
45static proc delete_dublicates_noteval(list l)
46{//proc delete_dublicates_noteval
47  list result= l;
48  int j; int k; int i;
49  int deleted = 0;
50  int is_equal;
51  for (i = 1; i<= size(l); i++)
52  {//Iterate over the different factorizations
53    for (j = i+1; j<= size(l); j++)
54    {//Compare the i'th factorization to the j'th
55      if (size(l[i])!= size(l[j]))
56      {//different sizes => not equal
57        j++;
58        continue;
59      }//different sizes => not equal
60      is_equal = 1;
61      for (k = 1; k <= size(l[i]);k++)
62      {//Compare every entry
63        if (l[i][k]!=l[j][k])
64        {
65          is_equal = 0;
66          break;
67        }
68      }//Compare every entry
69      if (is_equal == 1)
70      {//Delete this entry, because there is another equal one int the list
71        result = delete(result, i-deleted);
72        deleted = deleted+1;
73        break;
74      }//Delete this entry, because there is another equal one int the list
75    }//Compare the i'th factorization to the j'th
76  }//Iterate over the different factorizations
77  return(result);
78}//proc delete_dublicates_noteval
79
80//==================================================
81//deletes the double-entries in a list with
82//evaluating the products
83static proc delete_dublicates_eval(list l)
84{//proc delete_dublicates_eval
85  list result=l;
86  int j; int k; int i;
87  int deleted = 0;
88  int is_equal;
89  for (i = 1; i<= size(result); i++)
90  {//Iterating over all elements in result
91    for (j = i+1; j<= size(result); j++)
92    {//comparing with the other elements
93      if (product(result[i]) == product(result[j]))
94      {//There are two equal results; throw away that one with the smaller size
95        if (size(result[i])>=size(result[j]))
96        {//result[i] has more entries
97          result = delete(result,j);
98          continue;
99        }//result[i] has more entries
100        else
101        {//result[j] has more entries
102          result = delete(result,i);
103          i--;
104          break;
105        }//result[j] has more entries
106      }//There are two equal results; throw away that one with the smaller size
107    }//comparing with the other elements
108  }//Iterating over all elements in result
109  return(result);
110}//proc delete_dublicates_eval
111
112
113//==================================================*
114//given a list of factors g and a desired size nof, the following
115//procedure combines the factors, such that we recieve a
116//list of the length nof.
117static proc combinekfinlf(list g, int nof, intvec limits) //nof stands for "number of factors"
118{//Procedure combinekfinlf
119  list result;
120  int i; int j; int k; //iteration variables
121  list fc; //fc stands for "factors combined"
122  list temp; //a temporary store for factors
123  def nofgl = size(g); //nofgl stands for "number of factors of the given list"
124  if (nofgl == 0)
125  {//g was the empty list
126    return(result);
127  }//g was the empty list
128  if (nof <= 0)
129  {//The user wants to recieve a negative number or no element as a result
130    return(result);
131  }//The user wants to recieve a negative number or no element as a result
132  if (nofgl == nof)
133  {//There are no factors to combine
134    if (limitcheck(g,limits))
135    {
136      result = result + list(g);
137    }
138    return(result);
139  }//There are no factors to combine
140  if (nof == 1)
141  {//User wants to get just one factor
142    if (limitcheck(list(product(g)),limits))
143    {
144      result = result + list(list(product(g)));
145    }
146    return(result);
147  }//User wants to get just one factor
148  for (i = nof; i > 1; i--)
149  {//computing the possibilities that have at least one original factor from g
150    for (j = i; j>=1; j--)
151    {//shifting the window of combinable factors to the left
152      //fc below stands for "factors combined"
153      fc = combinekfinlf(list(g[(j)..(j+nofgl - i)]),nof - i + 1,limits);
154      for (k = 1; k<=size(fc); k++)
155      {//iterating over the different solutions of the smaller problem
156        if (j>1)
157        {//There are g_i before the combination
158          if (j+nofgl -i < nofgl)
159          {//There are g_i after the combination
160            temp = list(g[1..(j-1)]) + fc[k] + list(g[(j+nofgl-i+1)..nofgl]);
161          }//There are g_i after the combination
162          else
163          {//There are no g_i after the combination
164            temp = list(g[1..(j-1)]) + fc[k];
165          }//There are no g_i after the combination
166        }//There are g_i before the combination
167        if (j==1)
168        {//There are no g_i before the combination
169          if (j+ nofgl -i <nofgl)
170          {//There are g_i after the combination
171            temp = fc[k]+ list(g[(j + nofgl - i +1)..nofgl]);
172          }//There are g_i after the combination
173        }//There are no g_i before the combination
174        if (limitcheck(temp,limits))
175        {
176          result = result + list(temp);
177        }
178      }//iterating over the different solutions of the smaller problem
179    }//shifting the window of combinable factors to the left
180  }//computing the possibilities that have at least one original factor from g
181  for (i = 2; i<=nofgl/nof;i++)
182  {//getting the other possible results
183    result = result + combinekfinlf(list(product(list(g[1..i])))+list(g[(i+1)..nofgl]),nof,limits);
184  }//getting the other possible results
185  result = delete_dublicates_noteval(result);
186  return(result);
187}//Procedure combinekfinlf
188
189
190//==================================================*
191//merges two sets of factors ignoring common
192//factors
193static proc merge_icf(list l1, list l2, intvec limits)
194{//proc merge_icf
195  list g;
196  list f;
197  int i; int j;
198  if (size(l1)==0)
199  {
200    return(list());
201  }
202  if (size(l2)==0)
203  {
204    return(list());
205  }
206  if (size(l2)<=size(l1))
207  {//l1 will be our g, l2 our f
208    g = l1;
209    f = l2;
210  }//l1 will be our g, l2 our f
211  else
212  {//l1 will be our f, l2 our g
213    g = l2;
214    f = l1;
215  }//l1 will be our f, l2 our g
216  def result = combinekfinlf(g,size(f),limits);
217  for (i = 1 ; i<= size(result); i++)
218  {//Adding the factors of f to every possibility listed in temp
219    for (j = 1; j<= size(f); j++)
220    {
221      result[i][j] = result[i][j]+f[j];
222    }
223    if(!limitcheck(result[i],limits))
224    {
225      result = delete(result,i);
226      i--;
227    }
228  }//Adding the factors of f to every possibility listed in temp
229  return(result);
230}//proc merge_icf
231
232//==================================================*
233//merges two sets of factors with respect to the occurrence
234//of common factors
235static proc merge_cf(list l1, list l2, intvec limits)
236{//proc merge_cf
237  list g;
238  list f;
239  int i; int j;
240  list pre;
241  list post;
242  list candidate;
243  list temp;
244  int temppos;
245  if (size(l1)==0)
246  {//the first list is empty
247    return(list());
248  }//the first list is empty
249  if(size(l2)==0)
250  {//the second list is empty
251    return(list());
252  }//the second list is empty
253  if (size(l2)<=size(l1))
254  {//l1 will be our g, l2 our f
255    g = l1;
256    f = l2;
257  }//l1 will be our g, l2 our f
258  else
259  {//l1 will be our f, l2 our g
260    g = l2;
261    f = l1;
262  }//l1 will be our f, l2 our g
263  list M;
264  for (i = 2; i<size(f); i++)
265  {//finding common factors of f and g...
266    for (j=2; j<size(g);j++)
267    {//... with g
268      if (f[i] == g[j])
269      {//we have an equal pair
270        M = M + list(list(i,j));
271      }//we have an equal pair
272    }//... with g
273  }//finding common factors of f and g...
274  if (g[1]==f[1])
275  {//Checking for the first elements to be equal
276    M = M + list(list(1,1));
277  }//Checking for the first elements to be equal
278  if (g[size(g)]==f[size(f)])
279  {//Checking for the last elements to be equal
280    M = M + list(list(size(f),size(g)));
281  }//Checking for the last elements to be equal
282  list result;//= list(list());
283  while(size(M)>0)
284  {//set of equal pairs is not empty
285    temp = M[1];
286    temppos = 1;
287    for (i = 2; i<=size(M); i++)
288    {//finding the minimal element of M
289      if (M[i][1]<=temp[1])
290      {//a possible candidate that is smaller than temp could have been found
291        if (M[i][1]==temp[1])
292        {//In this case we must look at the second number
293          if (M[i][2]< temp[2])
294          {//the candidate is smaller
295            temp = M[i];
296            temppos = i;
297          }//the candidate is smaller
298        }//In this case we must look at the second number
299        else
300        {//The candidate is definately smaller
301          temp = M[i];
302          temppos = i;
303        }//The candidate is definately smaller
304      }//a possible candidate that is smaller than temp could have been found
305    }//finding the minimal element of M
306    M = delete(M, temppos);
307    if(temp[1]>1)
308    {//There are factors to combine before the equal factor
309      if (temp[1]<size(f))
310      {//The most common case
311        //first the combinations ignoring common factors
312        pre = merge_icf(list(f[1..(temp[1]-1)]),list(g[1..(temp[2]-1)]),limits);
313        post = merge_icf(list(f[(temp[1]+1)..size(f)]),list(g[(temp[2]+1..size(g))]),limits);
314        for (i = 1; i <= size(pre); i++)
315        {//all possible pre's...
316          for (j = 1; j<= size(post); j++)
317          {//...combined with all possible post's
318            candidate = pre[i]+list(f[temp[1]])+post[j];
319            if (limitcheck(candidate,limits))
320            {
321              result = result + list(candidate);
322            }
323          }//...combined with all possible post's
324        }//all possible pre's...
325        //Now the combinations with respect to common factors
326        post = merge_cf(list(f[(temp[1]+1)..size(f)]),list(g[(temp[2]+1..size(g))]),limits);
327        if (size(post)>0)
328        {//There are factors to combine
329          for (i = 1; i <= size(pre); i++)
330          {//all possible pre's...
331            for (j = 1; j<= size(post); j++)
332            {//...combined with all possible post's
333              candidate= pre[i]+list(f[temp[1]])+post[j];
334              if (limitcheck(candidate,limits))
335              {
336                result = result + list(candidate);
337              }
338            }//...combined with all possible post's
339          }//all possible pre's...
340        }//There are factors to combine
341      }//The most common case
342      else
343      {//the last factor is the common one
344        pre = merge_icf(list(f[1..(temp[1]-1)]),list(g[1..(temp[2]-1)]),limits);
345        for (i = 1; i<= size(pre); i++)
346        {//iterating over the possible pre-factors
347          candidate = pre[i]+list(f[temp[1]]);
348          if (limitcheck(candidate,limits))
349          {
350            result = result + list(candidate);
351          }
352        }//iterating over the possible pre-factors
353      }//the last factor is the common one
354    }//There are factors to combine before the equal factor
355    else
356    {//There are no factors to combine before the equal factor
357      if (temp[1]<size(f))
358      {//Just a check for security
359        //first without common factors
360        post=merge_icf(list(f[(temp[1]+1)..size(f)]),list(g[(temp[2]+1..size(g))]),limits);
361        for (i = 1; i<=size(post); i++)
362        {
363          candidate = list(f[temp[1]])+post[i];
364          if (limitcheck(candidate,limits))
365          {
366            result = result + list(candidate);
367          }
368        }
369        //Now with common factors
370        post = merge_cf(list(f[(temp[1]+1)..size(f)]),list(g[(temp[2]+1..size(g))]),limits);
371        if(size(post)>0)
372        {//we could find other combinations
373          for (i = 1; i<=size(post); i++)
374          {
375            candidate = list(f[temp[1]])+post[i];
376            if (limitcheck(candidate,limits))
377            {
378              result = result + list(candidate);
379            }
380          }
381        }//we could find other combinations
382      }//Just a check for security
383    }//There are no factors to combine before the equal factor
384  }//set of equal pairs is not empty
385  return(result);
386}//proc merge_cf
387
388
389//==================================================*
390//merges two sets of factors
391
392static proc mergence(list l1, list l2, intvec limits)
393{//Procedure mergence
394  list g;
395  list f;
396  int l; int k;
397  list F;
398  if (size(l2)<=size(l1))
399  {//l1 will be our g, l2 our f
400    g = l1;
401    f = l2;
402  }//l1 will be our g, l2 our f
403  else
404  {//l1 will be our f, l2 our g
405    g = l2;
406    f = l1;
407  }//l1 will be our f, l2 our g
408  list result;
409  for (l = size(f); l>=1; l--)
410  {//all possibilities to combine the factors of f
411    F = combinekfinlf(f,l,limits);
412    for (k = 1; k<= size(F);k++)
413    {//for all possibilities of combinations of the factors of f
414      result = result + merge_cf(F[k],g,limits);
415      result = result + merge_icf(F[k],g,limits);
416    }//for all possibilities of combinations of the factors of f
417  }//all possibilities to combine the factors of f
418  return(result);
419}//Procedure mergence
420
421
422//==================================================
423//Checks, whether a list of factors doesn't exceed the given limits
424static proc limitcheck(list g, intvec limits)
425{//proc limitcheck
426  int i;
427  if (size(limits)!=3)
428  {//check the input
429    return(0);
430  }//check the input
431  if(size(g)==0)
432  {
433    return(0);
434  }
435  def prod = product(g);
436  def limg = intvec(deg(prod,intvec(1,1)) ,deg(prod,intvec(1,0)),deg(prod,intvec(0,1)));
437  for (i = 1; i<=size(limg);i++)
438  {//the final check
439    if(limg[i]>limits[i])
440    {
441      return(0);
442    }
443  }//the final check
444  return(1);
445}//proc limitcheck
446
447
448//==================================================*
449//one factorization of a homogeneous polynomial
450//in the first Weyl Algebra
451static proc homogfacFirstWeyl(poly h)
452"USAGE: homogfacFirstWeyl(h); h is a homogeneous polynomial in the
453        first Weyl algebra with respect to the weight vector [-1,1]
454RETURN: list
455PURPOSE: Computes a factorization of a homogeneous polynomial h with
456         respect to the weight vector [-1,1] in the first Weyl algebra
457THEORY: @code{homogfacFirstWeyl} returns a list with a factorization of the given,
458        [-1,1]-homogeneous polynomial. If the degree of the polynomial is k with
459        k positive, the last k entries in the output list are the second
460        variable. If k is positive, the last k entries will be x. The other
461        entries will be irreducible polynomials of degree zero or 1 resp. -1.
462SEE ALSO: homogfacFirstWeyl_all
463"{//proc homogfacFirstWeyl
464  def r = basering;
465  poly hath;
466  int i; int j;
467  if (!homogwithorder(h,intvec(-1,1)))
468  {//The given polynomial is not homogeneous
469    return(list());
470  }//The given polynomial is not homogeneous
471  if (h==0)
472  {
473    return(list(0));
474  }
475  list result;
476  int m = deg(h,intvec(-1,1));
477  if (m!=0)
478  {//The degree is not zero
479    if (m <0)
480    {//There are more x than y
481      hath = lift(var(1)^(-m),h)[1,1];
482      for (i = 1; i<=-m; i++)
483      {
484        result = result + list(var(1));
485      }
486    }//There are more x than y
487    else
488    {//There are more y than x
489      hath = lift(var(2)^m,h)[1,1];
490      for (i = 1; i<=m;i++)
491      {
492        result = result + list(var(2));
493      }
494    }//There are more y than x
495  }//The degree is not zero
496  else
497  {//The degree is zero
498    hath = h;
499  }//The degree is zero
500  //beginning to transform x^i*y^i in theta(theta-1)...(theta-i+1)
501  list mons;
502  for(i = 1; i<=size(hath);i++)
503  {//Putting the monomials in a list
504    mons = mons+list(hath[i]);
505  }//Putting the monomials in a list
506  ring tempRing = 0,(x,y,theta),dp;
507  setring tempRing;
508  map thetamap = r,x,y;
509  list mons = thetamap(mons);
510  poly entry;
511  for (i = 1; i<=size(mons);i++)
512  {//transforming the monomials as monomials in theta
513    entry = leadcoef(mons[i]);
514    for (j = 0; j<leadexp(mons[i])[2];j++)
515    {
516      entry = entry * (theta-j);
517    }
518    mons[i] = entry;
519  }//transforming the monomials as monomials in theta
520  list azeroresult = factorize(sum(mons));
521  list azeroresult_return_form;
522  for (i = 1; i<=size(azeroresult[1]);i++)
523  {//rewrite the result of the commutative factorization
524    for (j = 1; j <= azeroresult[2][i];j++)
525    {
526      azeroresult_return_form = azeroresult_return_form + list(azeroresult[1][i]);
527    }
528  }//rewrite the result of the commutative factorization
529  setring(r);
530  map finalmap = tempRing,var(1),var(2),var(1)*var(2);
531  list tempresult = finalmap(azeroresult_return_form);
532  for (i = 1; i<=size(tempresult);i++)
533  {//factorizations of theta resp. theta +1
534    if(tempresult[i]==var(1)*var(2))
535    {
536      tempresult = insert(tempresult,var(1),i-1);
537      i++;
538      tempresult[i]=var(2);
539    }
540    if(tempresult[i]==var(2)*var(1))
541    {
542      tempresult = insert(tempresult,var(2),i-1);
543      i++;
544      tempresult[i]=var(1);
545    }
546  }//factorizations of theta resp. theta +1
547  result = tempresult+result;
548  return(result);
549}//proc homogfacFirstWeyl
550/* example */
551/* { */
552/*      "EXAMPLE:";echo=2; */
553/*      ring R = 0,(x,y),Ws(-1,1); */
554/*      def r = nc_algebra(1,1); */
555/*      setring(r); */
556/*      poly h = (x^2*y^2+1)*(x^4); */
557/*      homogfacFirstWeyl(h); */
558/* } */
559
560//==================================================
561//Computes all possible homogeneous factorizations
562static proc homogfacFirstWeyl_all(poly h)
563"USAGE: homogfacFirstWeyl_all(h); h is a homogeneous polynomial in the first Weyl algebra
564        with respect to the weight vector [-1,1]
565RETURN: list
566PURPOSE: Computes all factorizations of a homogeneous polynomial h with respect
567         to the weight vector [-1,1] in the first Weyl algebra
568THEORY: @code{homogfacFirstWeyl} returns a list with all factorization of the given,
569        homogeneous polynomial. It uses the output of homogfacFirstWeyl and permutes
570        its entries with respect to the commutation rule. Furthermore, if a
571        factor of degree zero is irreducible in K[\theta], but reducible in
572        the first Weyl algebra, the permutations of this element with the other
573        entries will also be computed.
574SEE ALSO: homogfacFirstWeyl
575"{//proc HomogfacFirstWeylAll
576  if (deg(h,intvec(1,1)) <= 0 )
577  {//h is a constant
578    return(list(list(h)));
579  }//h is a constant
580  def r = basering;
581  list one_hom_fac; //stands for one homogeneous factorization
582  int i; int j; int k;
583  //Compute again a homogeneous factorization
584  one_hom_fac = homogfacFirstWeyl(h);
585  if (size(one_hom_fac) == 0)
586  {//there is no homogeneous factorization or the polynomial was not homogeneous
587    return(list());
588  }//there is no homogeneous factorization or the polynomial was not homogeneous
589  //divide list in A0-Part and a list of x's resp. y's
590  list list_not_azero = list();
591  list list_azero;
592  list k_factor;
593  int is_list_not_azero_empty = 1;
594  int is_list_azero_empty = 1;
595  k_factor = list(one_hom_fac[1]);
596  if (absValue(deg(h,intvec(-1,1)))<size(one_hom_fac)-1)
597  {//There is a nontrivial A_0-part
598    list_azero = one_hom_fac[2..(size(one_hom_fac)-absValue(deg(h,intvec(-1,1))))];
599    is_list_azero_empty = 0;
600  }//There is a nontrivial A_0 part
601  for (i = 1; i<=size(list_azero)-1;i++)
602  {//in homogfacFirstWeyl, we factorized theta, and this will be made undone
603    if (list_azero[i] == var(1))
604    {
605      if (list_azero[i+1]==var(2))
606      {
607        list_azero[i] = var(1)*var(2);
608        list_azero = delete(list_azero,i+1);
609      }
610    }
611    if (list_azero[i] == var(2))
612    {
613      if (list_azero[i+1]==var(1))
614      {
615        list_azero[i] = var(2)*var(1);
616        list_azero = delete(list_azero,i+1);
617      }
618    }
619  }//in homogfacFirstWeyl, we factorized theta, and this will be made undone
620  if(deg(h,intvec(-1,1))!=0)
621  {//list_not_azero is not empty
622    list_not_azero =
623      one_hom_fac[(size(one_hom_fac)-absValue(deg(h,intvec(-1,1)))+1)..size(one_hom_fac)];
624    is_list_not_azero_empty = 0;
625  }//list_not_azero is not empty
626  //Map list_azero in K[theta]
627  ring tempRing = 0,(x,y,theta), dp;
628  setring(tempRing);
629  poly entry;
630  map thetamap = r,x,y;
631  if(!is_list_not_azero_empty)
632  {//Mapping in Singular is only possible, if the list before
633    //contained at least one element of the other ring
634    list list_not_azero = thetamap(list_not_azero);
635  }//Mapping in Singular is only possible, if the list before
636  //contained at least one element of the other ring
637  if(!is_list_azero_empty)
638  {//Mapping in Singular is only possible, if the list before
639    //contained at least one element of the other ring
640    list list_azero= thetamap(list_azero);
641  }//Mapping in Singular is only possible, if the list before
642  //contained at least one element of the other ring
643  list k_factor = thetamap(k_factor);
644  list tempmons;
645  for(i = 1; i<=size(list_azero);i++)
646  {//rewrite the polynomials in A1 as polynomials in K[theta]
647    tempmons = list();
648    for (j = 1; j<=size(list_azero[i]);j++)
649    {
650      tempmons = tempmons + list(list_azero[i][j]);
651    }
652    for (j = 1 ; j<=size(tempmons);j++)
653    {
654      entry = leadcoef(tempmons[j]);
655      for (k = 0; k < leadexp(tempmons[j])[2];k++)
656      {
657        entry = entry*(theta-k);
658      }
659      tempmons[j] = entry;
660    }
661    list_azero[i] = sum(tempmons);
662  }//rewrite the polynomials in A1 as polynomials in K[theta]
663  //Compute all permutations of the A0-part
664  list result;
665  int shift_sign;
666  int shift;
667  poly shiftvar;
668  if (size(list_not_azero)!=0)
669  {//Compute all possibilities to permute the x's resp. the y's in the list
670    if (list_not_azero[1] == x)
671    {//h had a negative weighted degree
672      shift_sign = 1;
673      shiftvar = x;
674    }//h had a negative weighted degree
675    else
676    {//h had a positive weighted degree
677      shift_sign = -1;
678      shiftvar = y;
679    }//h had a positive weighted degree
680    result = permpp(list_azero + list_not_azero);
681    for (i = 1; i<= size(result); i++)
682    {//adjust the a_0-parts
683      shift = 0;
684      for (j=1; j<=size(result[i]);j++)
685      {
686        if (result[i][j]==shiftvar)
687        {
688          shift = shift + shift_sign;
689        }
690        else
691        {
692          result[i][j] = subst(result[i][j],theta,theta + shift);
693        }
694      }
695    }//adjust the a_0-parts
696  }//Compute all possibilities to permute the x's resp. the y's in the list
697  else
698  {//The result is just all the permutations of the a_0-part
699    result = permpp(list_azero);
700  }//The result is just all the permutations of the a_0 part
701  if (size(result)==0)
702  {
703    return(result);
704  }
705  //Now we are going deeper and search for theta resp. theta + 1, substitute
706  //them by xy resp. yx and go on permuting
707  int found_theta;
708  int thetapos;
709  list leftpart;
710  list rightpart;
711  list lparts;
712  list rparts;
713  list tempadd;
714  for (i = 1; i<=size(result) ; i++)
715  {//checking every entry of result for theta or theta +1
716    found_theta = 0;
717    for(j=1;j<=size(result[i]);j++)
718    {
719      if (result[i][j]==theta)
720      {//the jth entry is theta and can be written as x*y
721        thetapos = j;
722        result[i]= insert(result[i],x,j-1);
723        j++;
724        result[i][j] = y;
725        found_theta = 1;
726        break;
727      }//the jth entry is theta and can be written as x*y
728      if(result[i][j] == theta +1)
729      {
730        thetapos = j;
731        result[i] = insert(result[i],y,j-1);
732        j++;
733        result[i][j] = x;
734        found_theta = 1;
735        break;
736      }
737    }
738    if (found_theta)
739    {//One entry was theta resp. theta +1
740      leftpart = result[i];
741      leftpart = leftpart[1..thetapos];
742      rightpart = result[i];
743      rightpart = rightpart[(thetapos+1)..size(rightpart)];
744      lparts = list(leftpart);
745      rparts = list(rightpart);
746      //first deal with the left part
747      if (leftpart[thetapos] == x)
748      {
749        shift_sign = 1;
750        shiftvar = x;
751      }
752      else
753      {
754        shift_sign = -1;
755        shiftvar = y;
756      }
757      for (j = size(leftpart); j>1;j--)
758      {//drip x resp. y
759        if (leftpart[j-1]==shiftvar)
760        {//commutative
761          j--;
762          continue;
763        }//commutative
764        if (deg(leftpart[j-1],intvec(-1,1,0))!=0)
765        {//stop here
766          break;
767        }//stop here
768        //Here, we can only have a a0- part
769        leftpart[j] = subst(leftpart[j-1],theta, theta + shift_sign);
770        leftpart[j-1] = shiftvar;
771        lparts = lparts + list(leftpart);
772      }//drip x resp. y
773      //and now deal with the right part
774      if (rightpart[1] == x)
775      {
776        shift_sign = 1;
777        shiftvar = x;
778      }
779      else
780      {
781        shift_sign = -1;
782        shiftvar = y;
783      }
784      for (j = 1 ; j < size(rightpart); j++)
785      {
786        if (rightpart[j+1] == shiftvar)
787        {
788          j++;
789          continue;
790        }
791        if (deg(rightpart[j+1],intvec(-1,1,0))!=0)
792        {
793          break;
794        }
795        rightpart[j] = subst(rightpart[j+1], theta, theta - shift_sign);
796        rightpart[j+1] = shiftvar;
797        rparts = rparts + list(rightpart);
798      }
799      //And now, we put all possibilities together
800      tempadd = list();
801      for (j = 1; j<=size(lparts); j++)
802      {
803        for (k = 1; k<=size(rparts);k++)
804        {
805          tempadd = tempadd + list(lparts[j]+rparts[k]);
806        }
807      }
808      tempadd = delete(tempadd,1); // The first entry is already in the list
809      result = result + tempadd;
810      continue; //We can may be not be done already with the ith entry
811    }//One entry was theta resp. theta +1
812  }//checking every entry of result for theta or theta +1
813  //map back to the basering
814  setring(r);
815  map finalmap = tempRing, var(1), var(2),var(1)*var(2);
816  list result = finalmap(result);
817  for (i=1; i<=size(result);i++)
818  {//adding the K factor
819    result[i] = k_factor + result[i];
820  }//adding the k-factor
821  result = delete_dublicates_noteval(result);
822  return(result);
823}//proc HomogfacFirstWeylAll
824/* example */
825/* { */
826/*      "EXAMPLE:";echo=2; */
827/*      ring R = 0,(x,y),Ws(-1,1); */
828/*      def r = nc_algebra(1,1); */
829/*      setring(r); */
830/*      poly h = (x^2*y^2+1)*(x^4); */
831/*      homogfacFirstWeyl_all(h); */
832/* } */
833
834//==================================================*
835//Computes all permutations of a given list
836static proc perm(list l)
837{//proc perm
838  int i; int j;
839  list tempresult;
840  list result;
841  if (size(l)==0)
842  {
843    return(list());
844  }
845  if (size(l)==1)
846  {
847    return(list(l));
848  }
849  for (i = 1; i<=size(l); i++ )
850  {
851    tempresult = perm(delete(l,i));
852    for (j = 1; j<=size(tempresult);j++)
853    {
854      tempresult[j] = list(l[i])+tempresult[j];
855    }
856    result = result+tempresult;
857  }
858  return(result);
859}//proc perm
860
861//==================================================
862//computes all permutations of a given list by
863//ignoring equal entries (faster than perm)
864static proc permpp(list l)
865{//proc permpp
866  int i; int j;
867  list tempresult;
868  list l_without_double;
869  list l_without_double_pos;
870  int double_entry;
871  list result;
872  if (size(l)==0)
873  {
874    return(list());
875  }
876  if (size(l)==1)
877  {
878    return(list(l));
879  }
880  for (i = 1; i<=size(l);i++)
881  {//Filling the list with unique entries
882    double_entry = 0;
883    for (j = 1; j<=size(l_without_double);j++)
884    {
885      if (l_without_double[j] == l[i])
886      {
887        double_entry = 1;
888        break;
889      }
890    }
891    if (!double_entry)
892    {
893      l_without_double = l_without_double + list(l[i]);
894      l_without_double_pos = l_without_double_pos + list(i);
895    }
896  }//Filling the list with unique entries
897  for (i = 1; i<=size(l_without_double); i++ )
898  {
899    tempresult = permpp(delete(l,l_without_double_pos[i]));
900    for (j = 1; j<=size(tempresult);j++)
901    {
902      tempresult[j] = list(l_without_double[i])+tempresult[j];
903    }
904    result = result+tempresult;
905  }
906  return(result);
907}//proc permpp
908
909//==================================================
910//factorization of the first Weyl Algebra
911
912//The following procedure just serves the purpose to
913//transform the input into an appropriate input for
914//the procedure sfacwa, where the ring must contain the
915//variables in a certain order.
916proc facFirstWeyl(poly h)
917"USAGE: facFirstWeyl(h); h a polynomial in the first Weyl algebra
918RETURN: list
919PURPOSE: compute all factorizations of a polynomial in the first Weyl algebra
920THEORY: Implements the new algorithm by A. Heinle and V. Levandovskyy, see the thesis of A. Heinle
921ASSUME: basering in the first Weyl algebra
922NOTE: Every entry of the output list is a list with factors for one possible factorization.
923The first factor is always a constant (1, if no nontrivial constant could be excluded).
924EXAMPLE: example facFirstWeyl; shows examples
925SEE ALSO: facSubWeyl, testNCfac, facFirstShift
926"{//proc facFirstWeyl
927  //Redefine the ring in my standard form
928  if (!isWeyl())
929  {//Our basering is not the Weyl algebra
930    return(list());
931  }//Our basering is not the Weyl algebra
932  if(nvars(basering)!=2)
933  {//Our basering is the Weyl algebra, but not the first
934    return(list());
935  }//Our basering is the Weyl algebra, but not the first
936  list result = list();
937  int i;int j; int k; int l; //counter
938  if (ringlist(basering)[6][1,2] == -1) //manual of ringlist will tell you why
939  {
940    def r = basering;
941    ring tempRing = ringlist(r)[1][1],(x,y),Ws(-1,1); // very strange:
942    // setting Wp(-1,1) leads to SegFault; to clarify why!!!
943    def NTR = nc_algebra(1,1);
944    setring NTR ;
945    map transf = r, var(2), var(1);
946    list resulttemp = sfacwa(transf(h));
947    setring(r);
948    map transfback = NTR, var(2),var(1);
949    result = transfback(resulttemp);
950  }
951  else { result = sfacwa(h);}
952  list recursivetemp;
953  for(i = 1; i<=size(result);i++)
954  {//recursively factorize factors
955    if(size(result[i])>2)
956    {//Nontrivial factorization
957      for (j=2;j<=size(result[i]);j++)
958      {//Factorize every factor
959        recursivetemp = facFirstWeyl(result[i][j]);
960        if(size(recursivetemp)>1)
961        {//we have a nontrivial factorization
962          for(k=1; k<=size(recursivetemp);k++)
963          {//insert factorized factors
964            if(size(recursivetemp[k])>2)
965            {//nontrivial
966              result = insert(result,result[i],i);
967              for(l = size(recursivetemp[k]);l>=2;l--)
968              {
969                result[i+1] = insert(result[i+1],recursivetemp[k][l],j);
970              }
971              result[i+1] = delete(result[i+1],j);
972            }//nontrivial
973          }//insert factorized factors
974        }//we have a nontrivial factorization
975      }//Factorize every factor
976    }//Nontrivial factorization
977  }//recursively factorize factors
978  if (size(result)==0)
979  {//only the trivial factorization could be found
980    result = list(list(1,h));
981  }//only the trivial factorization could be found
982  //now, refine the possible redundant list
983  return( delete_dublicates_noteval(result) );
984}//proc facFirstWeyl
985example
986{
987  "EXAMPLE:";echo=2;
988  ring R = 0,(x,y),dp;
989  def r = nc_algebra(1,1);
990  setring(r);
991  poly h = (x^2*y^2+x)*(x+1);
992  facFirstWeyl(h);
993}
994
995//This is the main program
996static proc sfacwa(poly h)
997"USAGE: sfacwa(h); h is a polynomial in the first Weyl algebra
998RETURN: list
999PURPOSE: Computes a factorization of a polynomial h in the first Weyl algebra
1000THEORY: @code{sfacwa} returns a list with some factorizations of the given
1001        polynomial. The possibilities of the factorization of the highest
1002        homogeneous part and those of the lowest will be merged. If during this
1003        procedure a factorization of the polynomial occurs, it will be added to
1004        the output list. For a more detailed description visit
1005        @url{http://www.math.rwth-aachen.de/\~Albert.Heinle}
1006SEE ALSO: homogfacFirstWeyl_all, homogfacFirstWeyl
1007"{//proc sfacwa
1008  if(homogwithorder(h,intvec(-1,1)))
1009  {
1010    return(homogfacFirstWeyl_all(h));
1011  }
1012  def r = basering;
1013  map invo = basering,-var(1),var(2);
1014  int i; int j; int k;
1015  intvec limits = deg(h,intvec(1,1)) ,deg(h,intvec(1,0)),deg(h,intvec(0,1));
1016  def prod;
1017  //end finding the limits
1018  poly maxh = jet(h,deg(h,intvec(-1,1)),intvec(-1,1))-jet(h,deg(h,intvec(-1,1))-1,intvec(-1,1));
1019  poly minh = jet(h,deg(h,intvec(1,-1)),intvec(1,-1))-jet(h,deg(h,intvec(1,-1))-1,intvec(1,-1));
1020  list result;
1021  list temp;
1022  list homogtemp;
1023  list M; list hatM;
1024  list f1 = homogfacFirstWeyl_all(maxh);
1025  list f2 = homogfacFirstWeyl_all(minh);
1026  int is_equal;
1027  poly hath;
1028  for (i = 1; i<=size(f1);i++)
1029  {//Merge all combinations
1030    for (j = 1; j<=size(f2); j++)
1031    {
1032      M = M + mergence(f1[i],f2[j],limits);
1033    }
1034  }//Merge all combinations
1035  for (i = 1 ; i<= size(M); i++)
1036  {//filter valid combinations
1037    if (product(M[i]) == h)
1038    {//We have one factorization
1039      result = result + list(M[i]);
1040      M = delete(M,i);
1041      continue;
1042    }//We have one factorization
1043    else
1044    {
1045      if (deg(h,intvec(-1,1))<=deg(h-product(M[i]),intvec(-1,1)))
1046      {
1047        M = delete(M,i);
1048        continue;
1049      }
1050      if (deg(h,intvec(1,-1))<=deg(h-product(M[i]),intvec(1,-1)))
1051      {
1052        M = delete(M,i);
1053        continue;
1054      }
1055    }
1056  }//filter valid combinations
1057  M = delete_dublicates_eval(M);
1058  while(size(M)>0)
1059  {//work on the elements of M
1060    hatM = list();
1061    for(i = 1; i<=size(M); i++)
1062    {//iterate over all elements of M
1063      hath = h-product(M[i]);
1064      temp = list();
1065      //First check for common inhomogeneous factors between hath and h
1066      if (involution(NF(involution(hath,invo), std(involution(ideal(M[i][1]),invo))),invo)==0)
1067      {//hath and h have a common factor on the left
1068        j = 1;
1069        f1 = M[i];
1070        if (j+1<=size(f1))
1071        {//Checking for more than one common factor
1072          while(involution(NF(involution(hath,invo),std(involution(ideal(product(f1[1..(j+1)])),invo))),invo)==0)
1073          {
1074            if (j+1<size(f1))
1075            {
1076              j++;
1077            }
1078            else
1079            {
1080              break;
1081            }
1082          }
1083        }//Checking for more than one common factor
1084        f2 = list(f1[1..j])+list(involution(lift(involution(product(f1[1..j]),invo),involution(hath,invo))[1,1],invo));
1085        temp = temp + merge_cf(f2,f1,limits);
1086      }//hath and h have a common factor on the left
1087      if (reduce(hath, std(ideal(M[i][size(M[i])])))==0)
1088      {//hath and h have a common factor on the right
1089        j = size(M[i]);
1090        f1 = M[i];
1091        if (j-1>0)
1092        {//Checking for more than one factor
1093          while(reduce(hath,std(ideal(product(f1[(j-1)..size(f1)]))))==0)
1094          {
1095            if (j-1>1)
1096            {
1097              j--;
1098            }
1099            else
1100            {
1101              break;
1102            }
1103          }
1104        }//Checking for more than one factor
1105        f2 = list(lift(product(f1[j..size(f1)]),hath)[1,1])+list(f1[j..size(f1)]);
1106        temp = temp + merge_cf(f2,M[i],limits);
1107      }//hath and h have a common factor on the right
1108      //and now the homogeneous
1109      maxh = jet(hath,deg(hath,intvec(-1,1)),intvec(-1,1))-jet(hath,deg(hath,intvec(-1,1))-1,intvec(-1,1));
1110      minh = jet(hath,deg(hath,intvec(1,-1)),intvec(1,-1))-jet(hath,deg(hath,intvec(1,-1))-1,intvec(1,-1));
1111      f1 = homogfacFirstWeyl_all(maxh);
1112      f2 = homogfacFirstWeyl_all(minh);
1113      for (j = 1; j<=size(f1);j++)
1114      {
1115        for (k=1; k<=size(f2);k++)
1116        {
1117          homogtemp = mergence(f1[j],f2[k],limits);
1118        }
1119      }
1120      for (j = 1; j<= size(homogtemp); j++)
1121      {
1122        temp = temp + mergence(homogtemp[j],M[i],limits);
1123      }
1124      for (j = 1; j<=size(temp); j++)
1125      {//filtering invalid entries in temp
1126        if(product(temp[j])==h)
1127        {//This is already a result
1128          result = result + list(temp[j]);
1129          temp = delete(temp,j);
1130          continue;
1131        }//This is already a result
1132        if (deg(hath,intvec(-1,1))<=deg(hath-product(temp[j]),intvec(-1,1)))
1133        {
1134          temp = delete(temp,j);
1135          continue;
1136        }
1137      }//filtering invalid entries in temp
1138      hatM = hatM + temp;
1139    }//iterate over all elements of M
1140    M = hatM;
1141    for (i = 1; i<=size(M);i++)
1142    {//checking for complete factorizations
1143      if (h == product(M[i]))
1144      {
1145        result = result + list(M[i]);
1146        M = delete(M,i);
1147        continue;
1148      }
1149    }//checking for complete factorizations
1150    M = delete_dublicates_eval(M);
1151  }//work on the elements of M
1152  //In the case, that there is none, write a constant factor before the factor of interest.
1153  for (i = 1 ; i<=size(result);i++)
1154  {//add a constant factor
1155    if (deg(result[i][1],intvec(1,1))!=0)
1156    {
1157      result[i] = insert(result[i],1);
1158    }
1159  }//add a constant factor
1160  result = delete_dublicates_noteval(result);
1161  return(result);
1162}//proc sfacwa
1163
1164
1165//==================================================
1166/*Singular has no way implemented to test polynomials
1167  for homogenity with respect to a weight vector.
1168  The following procedure does exactly this*/
1169static proc homogwithorder(poly h, intvec weights)
1170{//proc homogwithorder
1171  if(size(weights) != nvars(basering))
1172  {//The user does not know how many variables the current ring has
1173    return(0);
1174  }//The user does not know how many variables the current ring has
1175  int i;
1176  int dofp = deg(h,weights); //degree of polynomial
1177  for (i = 1; i<=size(h);i++)
1178  {
1179    if (deg(h[i],weights)!=dofp)
1180    {
1181      return(0);
1182    }
1183  }
1184  return(1);
1185}//proc homogwithorder
1186
1187//==================================================
1188//Testfac: Given a list with different factorizations of
1189// one polynomial, the following procedure checks
1190// whether they all refer to the same polynomial.
1191// If they do, the output will be a list, that contains
1192// the product of each factorization. If not, the empty
1193// list will be returned.
1194// If the optional argument # is given (i.e. the polynomial
1195// which is factorized by the elements of the given list),
1196// then we look, if the entries are factorizations of p
1197// and if not, a list with the products subtracted by p
1198// will be returned
1199proc testNCfac(list l, list #)
1200"USAGE: testNCfac(l[,p,b]); l is a list, p is an optional poly, b is 1 or 0
1201RETURN: Case 1: No optional argument. In this case the output is 1, if the
1202                entries in the given list represent the same polynomial or 0
1203                otherwise.
1204        Case 2: One optional argument p is given. In this case it returns 1,
1205                if all the entries in l are factorizations of p, otherwise 0.
1206        Case 3: Second optional b is given. In this case a list is returned
1207                containing the difference between the product of each entry in
1208                l and p.
1209ASSUME: basering is the first Weyl algebra, the entries of l are polynomials
1210PURPOSE: Checks whether a list of factorizations contains factorizations of
1211         the same element in the first Weyl algebra
1212THEORY: @code{testNCfac} multiplies out each factorization and checks whether
1213        each factorization was a factorization of the same element.
1214@* - if there is only a list given, the output will be 0, if it
1215     does not contain factorizations of the same element. Otherwise the output
1216     will be 1.
1217@* - if there is a polynomial in the second argument, then the procedure checks
1218     whether the given list contains factorizations of this polynomial. If it
1219     does, then the output depends on the third argument. If it is not given,
1220     the procedure will check whether the factorizations in the list
1221     l are associated to this polynomial and return either 1 or 0, respectively.
1222     If the third argument is given, the output will be a list with
1223     the length of the given one and in each entry is the product of one
1224     entry in l subtracted by the polynomial.
1225EXAMPLE: example testNCfac; shows examples
1226SEE ALSO: facFirstWeyl, facSubWeyl, facFirstShift
1227"{//proc testfac
1228  if (size(l)==0)
1229  {//The empty list is given
1230    return(list());
1231  }//The empty list is given
1232  if (size(#)>2)
1233  {//We want max. one optional argument
1234    return(list());
1235  }//We want max. one optional argument
1236  list result;
1237  int i; int j;
1238  if (size(#)==0)
1239  {//No optional argument is given
1240    int valid = 1;
1241    for (i = size(l);i>=1;i--)
1242    {//iterate over the elements of the given list
1243      if (size(result)>0)
1244      {
1245        if (product(l[i])!=result[size(l)-i])
1246        {
1247          valid = 0;
1248          break;
1249        }
1250      }
1251      result = insert(result, product(l[i]));
1252    }//iterate over the elements of the given list
1253    return(valid);
1254  }//No optional argument is given
1255  else
1256  {
1257    int valid = 1;
1258    for (i = size(l);i>=1;i--)
1259    {//iterate over the elements of the given list
1260      if (product(l[i])!=#[1])
1261      {
1262        valid = 0;
1263      }
1264      result = insert(result, product(l[i])-#[1]);
1265    }//iterate over the elements of the given list
1266    if(size(#)==2){return(result);}
1267    return(valid);
1268  }
1269}//proc testfac
1270example
1271{
1272  "EXAMPLE:";echo=2;
1273  ring r = 0,(x,y),dp;
1274  def R = nc_algebra(1,1);
1275  setring R;
1276  poly h = (x^2*y^2+1)*(x^2);
1277  def t1 = facFirstWeyl(h);
1278  //fist a correct list
1279  testNCfac(t1);
1280  //now a correct list with the factorized polynomial
1281  testNCfac(t1,h);
1282  //now we put in an incorrect list without a polynomial
1283  t1[3][3] = y;
1284  testNCfac(t1);
1285  // take h as additional input
1286  testNCfac(t1,h);
1287  // take h as additional input and output list of differences
1288  testNCfac(t1,h,1);
1289}
1290//==================================================
1291//Procedure facSubWeyl:
1292//This procedure serves the purpose to compute a
1293//factorization of a given polynomial in a ring, whose subring
1294//is the first Weyl algebra. The polynomial must only contain
1295//the two arguments, which are also given by the user.
1296
1297proc facSubWeyl(poly h, X, D)
1298"USAGE:  facSubWeyl(h,x,y); h, X, D polynomials
1299RETURN: list
1300ASSUME: X and D are variables of a basering, which satisfy DX = XD +1.
1301@* That is,  they generate the copy of the first Weyl algebra in a basering.
1302@* Moreover, h is a polynomial in X and D only.
1303PURPOSE: compute factorizations of the polynomial, which depends on X and D.
1304EXAMPLE: example facSubWeyl; shows examples
1305SEE ALSO: facFirstWeyl, testNCfac, facFirstShift
1306"{
1307    // basering can be anything having a Weyl algebra as subalgebra
1308  def @r = basering;
1309  //We begin to check the input for assumptions
1310  // which are: X,D are vars of the basering,
1311  if ( (isVar(X)!=1) || (isVar(D)!=1) || (size(X)>1) || (size(D)>1) ||
1312       (leadcoef(X) != number(1)) || (leadcoef(D) != number(1)) )
1313  {
1314    ERROR("expected pure variables as generators of a subalgebra");
1315  }
1316  // Weyl algebra:
1317  poly w = D*X-X*D-1; // [D,X]=1
1318  poly u = D*X-X*D+1; // [X,D]=1
1319  if (u*w!=0)
1320  {
1321    // that is no combination gives Weyl
1322    ERROR("2nd and 3rd argument do not generate a Weyl algebra");
1323  }
1324  // one of two is correct
1325  int isReverted = 0; // Reverted Weyl if dx=xd-1 holds
1326  if (u==0)
1327  {
1328    isReverted = 1;
1329  }
1330  // else: do nothing
1331  // DONE with assumptions, Input successfully checked
1332  intvec lexpofX = leadexp(X);
1333  intvec lexpofD = leadexp(D);
1334  int varnumX=1;
1335  int varnumD=1;
1336  while(lexpofX[varnumX] != 1)
1337  {
1338    varnumX++;
1339  }
1340  while(lexpofD[varnumD] != 1)
1341  {
1342    varnumD++;
1343  }
1344  /* VL : to add printlevel stuff */
1345
1346  if (isReverted)
1347  {
1348    ring firstweyl = 0,(var(varnumD),var(varnumX)),dp;
1349    def Firstweyl = nc_algebra(1,1);
1350    setring Firstweyl;
1351    ideal M = 0:nvars(@r);
1352    M[varnumX]=var(2);
1353    M[varnumD]=var(1);
1354    map Q = @r,M;
1355    poly h= Q(h);
1356  }
1357  else
1358  { // that is unReverted
1359    ring firstweyl = 0,(var(varnumX),var(varnumD)),dp;
1360    def Firstweyl = nc_algebra(1,1);
1361    setring Firstweyl;
1362    poly h= imap(@r,h);
1363  }
1364  list result = facFirstWeyl(h);
1365  setring @r;
1366  list result;
1367  if (isReverted)
1368  {
1369    // map swap back
1370    ideal M; M[1] = var(varnumD); M[2] = var(varnumX);
1371    map S = Firstweyl, M;
1372    result = S(result);
1373  }
1374  else
1375  {
1376    // that is unReverted
1377    result = imap(Firstweyl,result);
1378  }
1379  return(result);
1380}//proc facSubWeyl
1381example
1382{
1383  "EXAMPLE:";echo=2;
1384  ring r = 0,(x,y,z),dp;
1385  matrix D[3][3]; D[1,3]=-1;
1386  def R = nc_algebra(1,D); // x,z generate Weyl subalgebra
1387  setring R;
1388  poly h = (x^2*z^2+x)*x;
1389  list fact1 = facSubWeyl(h,x,z);
1390  // compare with facFirstWeyl:
1391  ring s = 0,(z,x),dp;
1392  def S = nc_algebra(1,1); setring S;
1393  poly h = (x^2*z^2+x)*x;
1394  list fact2 = facFirstWeyl(h);
1395  map F = R,x,0,z;
1396  list fact1 = F(fact1); // it is identical to list fact2
1397  testNCfac(fact1); // check the correctness again
1398}
1399//==================================================
1400
1401//==================================================
1402//************From here: Shift-Algebra**************
1403//==================================================
1404//==================================================*
1405//one factorization of a homogeneous polynomial
1406//in the first Shift Algebra
1407static proc homogfacFirstShift(poly h)
1408{//proc homogfacFirstShift
1409  def r = basering;
1410  poly hath;
1411  int i; int j;
1412  if (!homogwithorder(h,intvec(0,1)))
1413  {//The given polynomial is not homogeneous
1414    return(list());
1415  }//The given polynomial is not homogeneous
1416  if (h==0)
1417  {
1418    return(list(0));
1419  }
1420  list result;
1421  int m = deg(h,intvec(0,1));
1422  if (m>0)
1423  {//The degree is not zero
1424    hath = lift(var(2)^m,h)[1,1];
1425    for (i = 1; i<=m;i++)
1426    {
1427      result = result + list(var(2));
1428    }
1429  }//The degree is not zero
1430  else
1431  {//The degree is zero
1432    hath = h;
1433  }//The degree is zero
1434  ring tempRing = 0,(x),dp;
1435  setring tempRing;
1436  map thetamap = r,x,1;
1437  poly hath = thetamap(hath);
1438  list azeroresult = factorize(hath);
1439  list azeroresult_return_form;
1440  for (i = 1; i<=size(azeroresult[1]);i++)
1441  {//rewrite the result of the commutative factorization
1442    for (j = 1; j <= azeroresult[2][i];j++)
1443    {
1444      azeroresult_return_form = azeroresult_return_form + list(azeroresult[1][i]);
1445    }
1446  }//rewrite the result of the commutative factorization
1447  setring(r);
1448  map finalmap = tempRing,var(1);
1449  list tempresult = finalmap(azeroresult_return_form);
1450  result = tempresult+result;
1451  return(result);
1452}//proc homogfacFirstShift
1453
1454//==================================================
1455//Computes all possible homogeneous factorizations
1456static proc homogfacFirstShift_all(poly h)
1457{//proc HomogfacFirstShiftAll
1458  if (deg(h,intvec(1,1)) <= 0 )
1459  {//h is a constant
1460    return(list(list(h)));
1461  }//h is a constant
1462  def r = basering;
1463  list one_hom_fac; //stands for one homogeneous factorization
1464  int i; int j; int k;
1465  int shiftcounter;
1466  //Compute again a homogeneous factorization
1467  one_hom_fac = homogfacFirstShift(h);
1468  one_hom_fac = delete(one_hom_fac,1);
1469  if (size(one_hom_fac) == 0)
1470  {//there is no homogeneous factorization or the polynomial was not homogeneous
1471    return(list());
1472  }//there is no homogeneous factorization or the polynomial was not homogeneous
1473  list result = permpp(one_hom_fac);
1474  for (i = 1; i<=size(result);i++)
1475  {
1476    shiftcounter = 0;
1477    for (j = 1; j<=size(result[i]); j++)
1478    {
1479      if (result[i][j]==var(2))
1480      {
1481        shiftcounter++;
1482      }
1483      else
1484      {
1485        result[i][j] = subst(result[i][j], var(1), var(1)-shiftcounter);
1486      }
1487    }
1488    result[i] = insert(result[i],1);
1489  }
1490  result = delete_dublicates_noteval(result);
1491  return(result);
1492}//proc HomogfacFirstShiftAll
1493
1494//==================================================
1495//factorization of the first Shift Algebra
1496proc facFirstShift(poly h)
1497"USAGE: facFirstShift(h); h a polynomial in the first shift algebra
1498RETURN: list
1499PURPOSE: compute all factorizations of a polynomial in the first shift algebra
1500THEORY: Implements the new algorithm by A. Heinle and V. Levandovskyy, see the thesis of A. Heinle
1501ASSUME: basering in the first shift algebra
1502NOTE: Every entry of the output list is a list with factors for one possible factorization.
1503EXAMPLE: example facFirstShift; shows examples
1504SEE ALSO: testNCfac, facFirstWeyl, facSubWeyl
1505"{//facFirstShift
1506  if(nvars(basering)!=2)
1507  {//Our basering is the Shift algebra, but not the first
1508    ERROR("Basering is not the first shift algebra");
1509    return(list());
1510  }//Our basering is the Shift algebra, but not the first
1511  def r = basering;
1512  setring r;
1513  list LR = ringlist(r);
1514  number @n = leadcoef(LR[5][1,2]);
1515  poly @p = LR[6][1,2];
1516  if  ( @n!=number(1) )
1517  {
1518    ERROR("Basering is not the first shift algebra");
1519    return(list());
1520  }
1521  list result = list();
1522  int i;int j; int k; int l; //counter
1523  // create a ring with the ordering which makes shift algebra
1524  // graded
1525  // def r = basering; // done before
1526  ring tempRing = LR[1][1],(x,s),(a(0,1),Dp);
1527  def tempRingnc = nc_algebra(1,s);
1528  setring r;
1529  // information on relations
1530  if (@p == -var(1)) // reverted shift algebra
1531  {
1532    setring(tempRingnc);
1533    map transf = r, var(2), var(1);
1534    setring(r);
1535    map transfback = tempRingnc, var(2),var(1);
1536    //    result = transfback(resulttemp);
1537  }
1538  else
1539  {
1540    if ( @p == var(2)) // usual shift algebra
1541    {
1542      setring(tempRingnc);
1543      map transf = r, var(1), var(2);
1544      //    result = facshift(h);
1545      setring(r);
1546      map transfback = tempRingnc, var(1),var(2);
1547    }
1548    else
1549    {
1550      ERROR("Basering is not the first shift algebra");
1551      return(list());
1552    }
1553  }
1554  // main calls
1555  setring(tempRingnc);
1556  list resulttemp = facshift(transf(h));
1557  setring(r);
1558  result = transfback(resulttemp);
1559
1560  list recursivetemp;
1561  for(i = 1; i<=size(result);i++)
1562  {//recursively factorize factors
1563    if(size(result[i])>2)
1564    {//Nontrivial factorization
1565      for (j=2;j<=size(result[i]);j++)
1566      {//Factorize every factor
1567        recursivetemp = facFirstShift(result[i][j]);
1568        if(size(recursivetemp)>1)
1569        {//we have a nontrivial factorization
1570          for(k=1; k<=size(recursivetemp);k++)
1571          {//insert factorized factors
1572            if(size(recursivetemp[k])>2)
1573            {//nontrivial
1574              result = insert(result,result[i],i);
1575              for(l = size(recursivetemp[k]);l>=2;l--)
1576              {
1577                result[i+1] = insert(result[i+1],recursivetemp[k][l],j);
1578              }
1579              result[i+1] = delete(result[i+1],j);
1580            }//nontrivial
1581          }//insert factorized factors
1582        }//we have a nontrivial factorization
1583      }//Factorize every factor
1584    }//Nontrivial factorization
1585  }//recursively factorize factors
1586  //now, refine the possible redundant list
1587  return( delete_dublicates_noteval(result) );
1588}//facFirstShift
1589example
1590{
1591  "EXAMPLE:";echo=2;
1592  ring R = 0,(x,s),dp;
1593  def r = nc_algebra(1,s);
1594  setring(r);
1595  poly h = (s^2*x+x)*s;
1596  facFirstShift(h);
1597}
1598
1599static proc facshift(poly h)
1600"USAGE: facshift(h); h is a polynomial in the first Shift algebra
1601RETURN: list
1602PURPOSE: Computes a factorization of a polynomial h in the first Shift algebra
1603THEORY: @code{facshift} returns a list with some factorizations of the given
1604        polynomial. The possibilities of the factorization of the highest
1605        homogeneous part and those of the lowest will be merged. If during this
1606        procedure a factorization of the polynomial occurs, it will be added to
1607        the output list. For a more detailled description visit
1608        @url{http://www.math.rwth-aachen.de/\~Albert.Heinle}
1609SEE ALSO: homogfacFirstShift_all, homogfacFirstShift
1610"{//proc facshift
1611  if(homogwithorder(h,intvec(0,1)))
1612  {
1613    return(homogfacFirstShift_all(h));
1614  }
1615  def r = basering;
1616  map invo = basering,-var(1),-var(2);
1617  int i; int j; int k;
1618  intvec limits = deg(h,intvec(1,1)) ,deg(h,intvec(1,0)),deg(h,intvec(0,1));
1619  def prod;
1620  //end finding the limits
1621  poly maxh = jet(h,deg(h,intvec(0,1)),intvec(0,1))-jet(h,deg(h,intvec(0,1))-1,intvec(0,1));
1622  poly minh = jet(h,deg(h,intvec(0,-1)),intvec(0,-1))-jet(h,deg(h,intvec(0,-1))-1,intvec(0,-1));
1623  list result;
1624  list temp;
1625  list homogtemp;
1626  list M; list hatM;
1627  list f1 = homogfacFirstShift_all(maxh);
1628  list f2 = homogfacFirstShift_all(minh);
1629  int is_equal;
1630  poly hath;
1631  for (i = 1; i<=size(f1);i++)
1632  {//Merge all combinations
1633    for (j = 1; j<=size(f2); j++)
1634    {
1635      M = M + mergence(f1[i],f2[j],limits);
1636    }
1637  }//Merge all combinations
1638  for (i = 1 ; i<= size(M); i++)
1639  {//filter valid combinations
1640    if (product(M[i]) == h)
1641    {//We have one factorization
1642      result = result + list(M[i]);
1643      M = delete(M,i);
1644      continue;
1645    }//We have one factorization
1646    else
1647    {
1648      if (deg(h,intvec(0,1))<=deg(h-product(M[i]),intvec(0,1)))
1649      {
1650        M = delete(M,i);
1651        continue;
1652      }
1653      if (deg(h,intvec(0,-1))<=deg(h-product(M[i]),intvec(0,-1)))
1654      {
1655        M = delete(M,i);
1656        continue;
1657      }
1658    }
1659  }//filter valid combinations
1660  M = delete_dublicates_eval(M);
1661  while(size(M)>0)
1662  {//work on the elements of M
1663    hatM = list();
1664    for(i = 1; i<=size(M); i++)
1665    {//iterate over all elements of M
1666      hath = h-product(M[i]);
1667      temp = list();
1668      //First check for common inhomogeneous factors between hath and h
1669      if (involution(NF(involution(hath,invo), std(involution(ideal(M[i][1]),invo))),invo)==0)
1670      {//hath and h have a common factor on the left
1671        j = 1;
1672        f1 = M[i];
1673        if (j+1<=size(f1))
1674        {//Checking for more than one common factor
1675          while(involution(NF(involution(hath,invo),std(involution(ideal(product(f1[1..(j+1)])),invo))),invo)==0)
1676          {
1677            if (j+1<size(f1))
1678            {
1679              j++;
1680            }
1681            else
1682            {
1683              break;
1684            }
1685          }
1686        }//Checking for more than one common factor
1687        if (deg(product(f1[1..j]),intvec(1,1))!=0)
1688        {
1689          f2 = list(f1[1..j])+list(involution(lift(involution(product(f1[1..j]),invo),involution(hath,invo))[1,1],invo));
1690        }
1691        else
1692        {
1693          f2 = list(f1[1..j])+list(involution(lift(product(f1[1..j]),involution(hath,invo))[1,1],invo));
1694        }
1695        temp = temp + merge_cf(f2,f1,limits);
1696      }//hath and h have a common factor on the left
1697      if (reduce(hath, std(ideal(M[i][size(M[i])])))==0)
1698      {//hath and h have a common factor on the right
1699        j = size(M[i]);
1700        f1 = M[i];
1701        if (j-1>0)
1702        {//Checking for more than one factor
1703          while(reduce(hath,std(ideal(product(f1[(j-1)..size(f1)]))))==0)
1704          {
1705            if (j-1>1)
1706            {
1707              j--;
1708            }
1709            else
1710            {
1711              break;
1712            }
1713          }
1714        }//Checking for more than one factor
1715        f2 = list(lift(product(f1[j..size(f1)]),hath)[1,1])+list(f1[j..size(f1)]);
1716        temp = temp + merge_cf(f2,M[i],limits);
1717      }//hath and h have a common factor on the right
1718      //and now the homogeneous
1719      maxh = jet(hath,deg(hath,intvec(0,1)),intvec(0,1))-jet(hath,deg(hath,intvec(0,1))-1,intvec(0,1));
1720      minh = jet(hath,deg(hath,intvec(0,-1)),intvec(0,-1))-jet(hath,deg(hath,intvec(0,-1))-1,intvec(0,-1));
1721      f1 = homogfacFirstShift_all(maxh);
1722      f2 = homogfacFirstShift_all(minh);
1723      for (j = 1; j<=size(f1);j++)
1724      {
1725        for (k=1; k<=size(f2);k++)
1726        {
1727          homogtemp = mergence(f1[j],f2[k],limits);
1728        }
1729      }
1730      for (j = 1; j<= size(homogtemp); j++)
1731      {
1732        temp = temp + mergence(homogtemp[j],M[i],limits);
1733      }
1734      for (j = 1; j<=size(temp); j++)
1735      {//filtering invalid entries in temp
1736        if(product(temp[j])==h)
1737        {//This is already a result
1738          result = result + list(temp[j]);
1739          temp = delete(temp,j);
1740          continue;
1741        }//This is already a result
1742        if (deg(hath,intvec(0,1))<=deg(hath-product(temp[j]),intvec(0,1)))
1743        {
1744          temp = delete(temp,j);
1745          continue;
1746        }
1747      }//filtering invalid entries in temp
1748      hatM = hatM + temp;
1749    }//iterate over all elements of M
1750    M = hatM;
1751    for (i = 1; i<=size(M);i++)
1752    {//checking for complete factorizations
1753      if (h == product(M[i]))
1754      {
1755        result = result + list(M[i]);
1756        M = delete(M,i);
1757        continue;
1758      }
1759    }//checking for complete factorizations
1760    M = delete_dublicates_eval(M);
1761  }//work on the elements of M
1762  //In the case, that there is none, write a constant factor before the factor of interest.
1763  for (i = 1 ; i<=size(result);i++)
1764  {//add a constant factor
1765    if (deg(result[i][1],intvec(1,1))!=0)
1766    {
1767      result[i] = insert(result[i],1);
1768    }
1769  }//add a constant factor
1770  result = delete_dublicates_noteval(result);
1771  return(result);
1772}//proc facshift
1773
1774static proc refineFactList(list L)
1775{
1776  // assume: list L is an output of factorization proc
1777  // doing: remove doubled entries
1778  int s = size(L); int sm;
1779  int i,j,k,cnt;
1780  list M, U, A, B;
1781  A = L;
1782  k = 0;
1783  cnt  = 1;
1784  for (i=1; i<=s; i++)
1785  {
1786    if (size(A[i]) != 0)
1787    {
1788      M = A[i];
1789      //      "probing with"; M; i;
1790      B[cnt] = M; cnt++;
1791      for (j=i+1; j<=s; j++)
1792      {
1793        if ( isEqualList(M,A[j]) )
1794        {
1795          k++;
1796        // U consists of intvecs with equal pairs
1797          U[k] = intvec(i,j);
1798          A[j] = 0;
1799        }
1800      }
1801    }
1802  }
1803  kill A,U,M;
1804  return(B);
1805}
1806example
1807{
1808  "EXAMPLE:";echo=2;
1809  ring R = 0,(x,s),dp;
1810  def r = nc_algebra(1,1);
1811  setring(r);
1812  list l,m;
1813  l = list(1,s2+1,x,s,x+s);
1814  m = l,list(1,s,x,s,x),l;
1815  refineFactList(m);
1816}
1817
1818static proc isEqualList(list L, list M)
1819{
1820  // int boolean: 1=yes, 0 =no : test whether two lists are identical
1821  int s = size(L);
1822  if (size(M)!=s) { return(0); }
1823  int j=1;
1824  while ( (L[j]==M[j]) && (j<s) )
1825  {
1826    j++;
1827  }
1828  if (L[j]==M[j])
1829  {
1830    return(1);
1831  }
1832  return(0);
1833}
1834example
1835{
1836  "EXAMPLE:";echo=2;
1837  ring R = 0,(x,s),dp;
1838  def r = nc_algebra(1,1);
1839  setring(r);
1840  list l,m;
1841  l = list(1,s2+1,x,s,x+s);
1842  m = l;
1843  isEqualList(m,l);
1844}
1845
1846/*
1847  Example polynomials where one can find factorizations: K<x,y |yx=xy+1>
1848  (x^2+y)*(x^2+y);
1849  (x^2+x)*(x^2+y);
1850  (x^3+x+1)*(x^4+y*x+2);
1851  (x^2*y+y)*(y+x*y);
1852  y^3+x*y^3+2*y^2+2*(x+1)*y^2+y+(x+2)*y; //Example 5 Grigoriev-Schwarz.
1853  (y+1)*(y+1)*(y+x*y); //Landau Example projected to the first dimension.
1854*/
1855
1856
1857/* very hard things from Martin Lee:
1858// ex1, ex2
1859ring s = 0,(z,x),Ws(-1,1);
1860def S = nc_algebra(1,1); setring S;
1861poly a = 10z5x4+26z4x5+47z5x2-97z4x3; //Abgebrochen nach einer Stunde; yes, it takes long
1862def l= facFirstWeyl (a); l;
1863kill l;
1864poly b = -5328z8x5-5328z7x6+720z9x2+720z8x3-16976z7x4-38880z6x5-5184z7x3-5184z6x4-3774z5x5+2080z8x+5760z7x2-6144z6x3-59616z5x4+3108z3x6-4098z6x2-25704z5x3-21186z4x4+8640z6x-17916z4x3+22680z2x5+2040z5x-4848z4x2-9792z3x3+3024z2x4-10704z3x2-3519z2x3+34776zx4+12096zx3+2898x4-5040z2x+8064x3+6048x2; //Abgebrochen nach 1.5 Stunden; seems to be very complicated
1865def l= facFirstWeyl (b); l;
1866
1867// ex3: there was difference in answers => fixed
1868LIB "ncfactor.lib";
1869ring r = 0,(x,y,z),dp;
1870matrix D[3][3]; D[1,3]=-1;
1871def R = nc_algebra(1,D);
1872setring R;
1873poly g= 7*z4*x+62*z3+26*z;
1874def l1= facSubWeyl (g, x, z);
1875l1;
1876//---- other ring
1877ring s = 0,(x,z),dp;
1878def S = nc_algebra(1,-1); setring S;
1879poly g= 7*z4*x+62*z3+26*z;
1880def l2= facFirstWeyl (g);
1881l2;
1882map F = R,x,0,z;
1883list l1 = F(l1);
1884l1;
1885//---- so the answers look different, check them!
1886testNCfac(l2); // ok
1887testNCfac(l1); // was not ok, but now it's been fixed!!!
1888
1889// selbst D und X so vertauschen dass sie erfuellt ist : ist gemacht
1890
1891*/
1892
1893/*
1894// bug from M Lee
1895LIB "ncfactor.lib";
1896ring s = 0,(z,x),dp;
1897def S = nc_algebra(1,1); setring S;
1898poly f= -60z4x2-54z4-56zx3-59z2x-64;
1899def l= facFirstWeyl (f);
1900l; // before: empty list; after fix: 1 entry, f is irreducible
1901poly g = 75z3x2+92z3+24;
1902def l= facFirstWeyl (g);
1903l; //before: empty list, now: correct
1904*/
1905
1906/* more things from Martin Lee; fixed
1907ring R = 0,(x,s),dp;
1908def r = nc_algebra(1,s);
1909setring(r);
1910poly h = (s2*x+x)*s;
1911h= h* (x+s);
1912def l= facFirstShift(h);
1913l; // contained doubled entries: not anymore, fixed!
1914
1915ring R = 0,(x,s),dp;
1916def r = nc_algebra(1,-1);
1917setring(r);
1918poly h = (s2*x+x)*s;
1919h= h* (x+s);
1920def l= facFirstWeyl(h);
1921l; // contained doubled entries: not anymore, fixed!
1922
1923*/
Note: See TracBrowser for help on using the repository browser.