source: git/Singular/LIB/chern.lib @ 1e1990

spielwiese
Last change on this file since 1e1990 was 1e1990, checked in by Frédéric Chapoton <chapoton@…>, 17 months ago
fixing various typos (found using egrep)
  • Property mode set to 100644
File size: 126.4 KB
Line 
1////////////////////////////////////////////////////////////////
2version = "version chern.lib 4.1.3.0 Apr_2020 "; // $Id$
3category = "Chern classes";
4info="
5LIBRARY:  chern.lib    Symbolic Computations with Chern classes,
6                       Computation of Chern classes
7
8AUTHOR:  Oleksandr Iena,      o.g.yena@gmail.com
9
10OVERVIEW:
11  A toolbox for symbolic computations with Chern classes.
12  The Aluffi's algorithms for computation of characteristic classes of algebraic varieties
13  (Segre, Fulton, Chern-Schwartz-MacPherson classes) are implemented as well.
14
15
16REFERENCES:
17  [1] Aluffi, Paolo     Computing characteristic classes of projective schemes.
18                        Journal of Symbolic Computation, 35 (2003), 3-19.
19  [2] Iena, Oleksandr,  On symbolic computations with Chern classes:
20                        remarks on the library chern.lib for Singular,
21                        http://hdl.handle.net/10993/22395, 2015.
22  [3] Lascoux, Alain,   Classes de Chern d'un produit tensoriel.
23                        C. R. Acad. Sci., Paris, Ser. A 286, 385-387 (1978).
24  [4] Manivel, Laurent  Chern classes of tensor products, arXiv 1012.0014, 2010.
25
26PROCEDURES:
27  symm(l [,N]);             symmetric functions in the entries of l
28  symNsym(f, c);            symmetric and non-symmetric parts of a polynomial f
29  CompleteHomog(N, l);      complete homogeneous symmetric functions
30  segre(N, c);              Segre classes in terms of Chern classes
31  chern(N, s);              Chern classes in terms of Segre classes
32  chNum(N, c);              the non-zero Chern numbers in degree N in the entries of c
33  chNumbers(N, c);          the Chern numbers in degree N in the entries of c
34  sum_of_powers(k, l);      the sum of k-th powers of the entries of l
35  powSumSym(c [,N]);        the sums of powers [up to degree N] in terms
36                            of the elementary symmetric polynomials (entries of l)
37  chAll(c [,N]);            Chern character in terms of the Chern classes
38  chAllInv(c);              Chern classes in terms of the Chern character
39  chHE(c);                  the highest term of the Chern character
40  ChernRootsSum(a, b);      the Chern roots of a direct sum
41  chSum(c, C);              the Chern classes of a direct sum
42  ChernRootsDual(l);        the Chern roots of the dual vector bundle
43  chDual(c);                the Chern classes of the dual vector bundle
44  ChernRootsProd(l, L);     the Chern roots of a tensor product of vector bundles
45  chProd(r, c, R, C [,N]);  Chern classes of a tensor product of vector bundles
46  chProdE(c, C);            Chern classes of a tensor product of vector bundles
47  chProdL(r, c, R, C);      Chern classes of a tensor product of vector bundles
48  chProdLP(r, c, R, C);     total Chern class of a tensor product of vector bundles
49  chProdM(r, c, R, C);      Chern classes of a tensor product of vector bundles
50  chProdMP(r, c, R, C);     total Chern class of a tensor product of vector bundles
51  ChernRootsHom(l, L);      the Chern roots of a Hom vector bundle
52  chHom(r, c, R, C [,N]);   Chern classes of the Hom-vector bundle
53  ChernRootsSymm(n, l);     the Chern roots of the n-th symmetric power
54                            of a vector bundle with Chern roots from l
55  ChernRootsWedge(n, l);    the Chern roots of the n-th exterior power
56                            of a vector bundle with Chern roots from l
57  chSymm(k, r, c [,p]);     the rank and the Chern classes of the k-th symmetric power
58                            of a vector bundle of rank r with Chern classes c
59  chSymm2L(r, c);           the rank and the Chern classes of the second symmetric power
60                            of a vector bundle of rank r with Chern classes c
61  chSymm2LP(r, c);          the total Chern class of the second symmetric power
62                            of a vector bundle of rank r with Chern classes c
63  chWedge(k, r, c [,p]);    the rank and the Chern classes of the k-th exterior power
64                            of a vector bundle of rank r with Chern classes c
65  chWedge2L(r, c);          the rank and the Chern classes of the second exterior power
66                            of a vector bundle of rank r with Chern classes c
67  chWedge2LP(r, c);         the total Chern class of the second exterior power
68                            of a vector bundle of rank r with Chern classes c
69  todd(c [,n]);             the Todd class
70  toddE(c);                 the highest term of the Todd class
71  Bern(n);                  the second Bernoulli numbers
72  tdCf(n);                  the coefficients of the Todd class of a line bundle
73  tdTerms(n, f);            the terms of the Todd class of a line bundle
74                            corresponding to the Chern root t
75  tdFactor(n, t);           the Todd class of a line bundle corresponding
76                            to the Chern root t
77  cProj(n);                 the total Chern class of (the tangent bundle on)
78                            the projective space P_n
79  chProj(n);                the Chern character of (the tangent bundle on)
80                            the projective space P_n
81  tdProj(n);                the Todd class of (the tangent bundle on)
82                            the projective space P_n
83  eulerChProj(n, r, c);     Euler characteristic of a vector bundle on
84                            the projective space P_n
85                            via Hirzebruch-Riemann-Roch theorem
86  chNumbersProj(n);         the Chern numbers of the projective space P_n
87  classpoly(l, t);          polynomial in t with coefficients from l
88                            (without constant term)
89  chernPoly(l, t);          Chern polynomial (constant term 1)
90  chernCharPoly(r, l, t);   polynomial in t corresponding to the Chern character
91                            (constant term r)
92  toddPoly(td, t);          polynomial in t corresponding to the Todd class
93                            (constant term 1)
94  rHRR(N, ch, td);          the main ingredient of the right-hand side
95                            of the Hirzebruch-Riemann-Roch formula
96  SchurS(I, S);             the Schur polynomial corresponding to partition I
97                            in terms of the Segre classes S
98  SchurCh(I, C);            the Schur polynomial corresponding to partition I
99                            in terms of the Chern classes C
100  part(m, n);               partitions of integers not exceeding n
101                            into m non-negative summands
102  dualPart(I [,N]);         partition dual to I
103  PartC(I, m);              the complement of a partition with respect to m
104  partOver(n, J);           partitions over a given partition J with summands not exceeding n
105  partUnder(J);             partitions under a given partition J
106  SegreA(I);                Segre class of the projective subscheme defined by I
107  FultonA(I);               Fulton class of the projective subscheme defined by I
108  CSMA(I);                  Chern-Schwartz-MacPherson class of the
109                            projective subscheme defined by I
110  EulerAff(I);              Euler characteristic of the affine subvariety defined by I
111  EulerProj(I);             Euler characteristic of the projective subvariety defined by I
112";
113
114LIB "general.lib";
115LIB "lrcalc.lib"; // needed for chProdM(..) and chProdMP(..)
116//----------------------------------------------------------
117
118proc symm(list l, list #)
119"USAGE:   symm(l [,n]);  l a list of polynomials, n integer
120RETURN:   list of polynomials
121PURPOSE:  computes the list of elementary symmetric functions in the entries of l
122EXAMPLE:  example symm; shows an example
123NOTE:     makes sense only for a list of polynomials
124"
125{
126  int N=size(l);
127  int n=size(l);
128  if(size(#)!=0)
129  {
130    if( is_integer(#[1]) )
131    {
132      N = #[1];
133    }
134  }
135  if(n==0) // if the list is empty, return the empty list
136  {
137    return(list());
138  }
139  else
140  {
141    int i, j;
142    list rez=list(1, l[1]);
143    for(i=2; i<=n; i++)
144    {
145      if( i<=N )
146      {
147        rez=rez+list(0);
148      }
149      for(j = min(i, N); j>=1; j--)
150      {
151        rez[j+1] = rez[j+1] + rez[j]*l[i];
152      }
153    }
154    return(delete(rez, 1));
155  }
156}
157example
158{
159  "EXAMPLE:";echo =2;
160  // elementary symmetric functions in x, y, z:
161  ring r = 0, (x, y, z), dp;
162  list l=(x, y, z);
163  print(symm(l));
164
165  //now let us compute only the first two symmetric polynomials in a(1), ... , a(10)
166  ring q= 0,(a(1..10)), dp;
167  list l=a(1..10);
168  print(symm(l, 2));
169}
170//-----------------------------------------------------------------------
171
172proc symNsym(poly f, list c)
173"USAGE:   symNsym(f, c);  f polynomial; c list of polynomials
174RETURN:   list with 2 poly entries
175PURPOSE:  computes a symmetric and a non-symmetric part of f
176          in terms of the elementary symmetric functions from c
177          as well a non-symmetric remainder
178EXAMPLE:  example symNsym; shows an example
179NOTE:     constants are considered symmetric
180"
181{
182  ideal V=variables(f); // variables f depends on
183  int nV=size(V); // their number
184  if(nV==0)
185  {
186    return(list(f, 0));
187  }
188  // now f is non-constant and does depend on some variables
189  c=append_by_zeroes(nV, c); // append c by zeroes if it is too short
190  def br@=basering; // remember the base ring
191  // add additional variables to the base ring
192  int ii;
193  list l2 = ringlist(basering)[2];
194  for (ii = 1; ii <= nV; ii++)
195  {
196   l2[size(l2)+1] = "c@("+string(ii)+")";
197  }
198    for (ii = 1; ii <= nV; ii++)
199  {
200   l2[size(l2)+1] = "A@("+string(ii)+")";
201  }
202  ring r@ = create_ring(ring_list(basering)[1], l2, "dp", "no_minpoly");
203  ideal V=fetch(br@,V);
204  poly f=fetch(br@,f);
205  int i;
206  for(i=1; i<=nV; i++)
207  {
208    f=subst(f, V[i], A@(i) ); // rename the variables of f into A@(1..nV)
209  }
210  int N1=nvars(basering)-nV+1; // the number of variable A@(1)
211  poly rez1=0; // to be the expression in c@(i) of the symmetric part of f
212  poly rez2=0; // to be the remainder
213  poly mon; // monomial in c@(i)
214  poly monc; // the corresponding expression in A@(i)
215  list l=symm(list(A@(1..nV) )); // symmetric functions in A@(i)
216  intvec v=leadexp(f), 0; // the exponent of the leading monomial
217  int exponent;
218  // We proceed as if the initial polynomial were symmetric.
219  // Under this assumption the leading monomial will always be of the form
220  // A@(1)^n1 * A@(2)^n2 * ... * A@(nV)^nnV, n1 >= n2 >= ... >= nnV.
221  // Everything which contradicts this assumption is considered as a part of the remainder.
222  while(v[N1]!=0)
223  {
224    mon=leadcoef(f); // leading coefficient of f
225    monc=mon;
226    for(i=1; i<=nV && mon !=0 ;i++ )
227    {
228      exponent = v[N1+i-1]-v[N1+i];
229      if( exponent >=0 ) // symmetric case
230      {
231        mon = mon*c@(i)^exponent;
232        monc = monc*l[i]^exponent; // has the same leading coefficient as f
233      }
234      else // not the symmetric case
235      {
236        mon=0;
237        monc=0;
238      }
239    }
240    if(mon==0) // not the symmetric case
241    {
242      rez2=rez2+lead(f);
243      f=f-lead(f);
244    }
245    else // symmetric case
246    {
247      rez1=rez1+mon; // add a monomial
248      f=f-monc; // subtract the monomial
249    }
250    v=leadexp(f), 0;
251  }
252  while( leadexp(f)!=0 )
253  {
254    rez2=rez2+lead(f);
255    f=f-lead(f);
256  }
257  rez1=rez1+f;
258  setring br@; // come back to the initial base ring
259  // define the specialization homomorphism
260  execute("map FF = r@,"+varstr(br@)+",c[1..nV], V[1..nV];");
261  return( list( FF(rez1), FF(rez2) ) );
262}
263example
264{
265  "EXAMPLE:";echo=2;
266  ring r=0, (x,y,z, c(1..3)), dp;
267  list l=c(1..3);
268  // The symmetric part of f = 3x2 + 3y2 + 3z2 + 7xyz + y
269  // in terms of the elementary symmetric functions c(1), c(2), c(3)
270  // and the remainder
271  poly f = 3x2 + 3y2 + 3z2 + 7xyz + y;
272  print( symNsym(f, l) );
273  // Take a symmetric polynomial in variables x and z
274  f=x2+xz+z2;
275  // Express it in terms of the elementary the symmetric functions
276  print( symNsym(f, l)[1]);
277}
278//-------------------------------------------------------------------------------------------
279
280proc CompleteHomog(int N, list c)
281"USAGE:   CompleteHomog(N, c);  N integer, c list of polynomials
282RETURN:   list of polynomials
283PURPOSE:  computes the list of the complete homogeneous symmetric polynomials
284          in terms of the elementary symmetric polynomials (entries of c)
285EXAMPLE:  example CompleteHomog; shows an example
286NOTE:
287"
288{
289  c=append_by_zeroes(N, c);
290  if(N<0) // if N is negative, return the empty list
291  {
292    return(list());
293  }
294  list rez=list(1); // the result will be computed here
295  int i, j;
296  int sign;
297  poly f;
298  for(i=1; i<=N; i++) // use the recursive formula
299  {
300    f=0;
301    sign=1;
302    for(j=1;j<=i; j++) // compute the next complete homogeneous symmetric polynomial
303    {
304      f=f+sign*c[j]*rez[i-j+1];
305      sign=-sign;
306    }
307    rez=rez+( list(f)  );
308  }
309  return(rez);
310}
311example
312{
313  "EXAMPLE:";echo =2;
314  ring r = 0, (x(1..3)), dp;
315  list l=x(1..3);
316  //Complete homogeneous symmetric polynomials up to degree 3 in variables x(1), x(2), x(3)
317  print( CompleteHomog(3, l) );
318}
319//-----------------------------------------------------------------------
320
321proc segre(list c, list #)
322"USAGE:   segre(c[, N]); c list of polynomials, N integer
323RETURN:   list of polynomials
324PURPOSE:  computes the list of the Segre classes up to degree N
325          in terms of the Chern classes from c
326EXAMPLE:  example segre; shows an example
327NOTE:
328"
329{
330  int N;
331  if(size(#)>0)
332  {
333    if( is_integer(#[1]) )
334    {
335      N=#[1];
336    }
337  }
338  else
339  {
340    N=size(c);
341  }
342  c=append_by_zeroes(N, c);
343  if(N<0) // if N is negative, return the empty list
344  {
345    return(list());
346  }
347  list rez=list(1); // the result will be computed here
348  int i, j;
349  poly f;
350  for(i=1; i<=N; i++) // use the recursive formula
351  {
352    f=0;
353    for(j=1;j<=i; j++) // compute the next Segre class
354    {
355      f=f-c[j]*rez[i-j+1];
356    }
357    rez=rez+( list(f)  );
358  }
359  return(delete(rez,1));
360}
361example
362{
363  "EXAMPLE:";echo =2;
364  ring r = 0, (c(1..3)), dp;
365  list l=c(1..3);
366  //Segre classes up to degree 5 in Chern classes c(1), c(2), c(3)
367  print( segre(l, 5) );
368}
369//-----------------------------------------------------------------------
370
371proc chern(list s, list #)
372"USAGE:   chern(s);  s list of polynomials
373RETURN:   list of polynomials
374PURPOSE:  computes the list of the Chern classes up to degree N
375          in terms of the Segre classes from s
376EXAMPLE:  example chern; shows an example
377NOTE:
378"
379{
380  return( segre(s, #) );
381}
382example
383{
384  "EXAMPLE:"; echo =2;
385  ring r = 0, (s(1..3)), dp;
386  list l=s(1..3);
387  // Chern classes in Segre classes s(1), s(2), s(3)
388  print( chern(l) );
389  // This procedure is inverse to segre(...). Indeed:
390  print( segre(chern(l), 3) );
391}
392//-----------------------------------------------------------------------
393
394proc chNum(int N, list c)
395"USAGE:   chNum(N, c);  N integer, c list
396RETURN:   list
397PURPOSE:  computes the Chern numbers of a vector bundle with Chern classes c
398          on a complex manifold (variety) of dimension N,
399          the zeroes corresponding to the higher zero Chern classes are ignored
400EXAMPLE:  example chNumbers; shows an example
401NOTE:     computes basically the partitions of N
402          in summands not greater than the length of c
403"
404{
405  int n=size(c);
406  if(N<0)
407  {
408    print("");
409    return( list() );
410  }
411  if( (n==0) || (N==0)  )
412  {
413    return(list(1));
414  }
415  if(n==1) // if there is only one entry in the list
416  {
417    return(list(c[1]^N));
418  }
419  int i;
420  int j;
421  poly f; // the powers of the last variable will be stored here
422  list l=delete(c, n); // delete the last variable
423  list L;
424  list rez=chNum(N, l); // monomials not involving the last variable
425  for(i=1;i<=(N div n); i++) // add the monomials involving the last variable
426  {
427    f=c[n]^i; // the power of the last variable
428    // monomials without the last variable that,
429    // multiplied by the i-th power of the last variable,
430    // give a monomial of the required type
431    L=chNum(N-n*i, l);
432    for(j=1; j<=size(L) ;j++) // multiply every such monomial
433    {
434      L[j]=L[j]*f; // by the i-th power of the last variable
435    }
436    rez=rez+L; // add the monomials involving the i-th power of the last variable
437  }
438  return(rez);
439}
440example
441{
442  "EXAMPLE:";echo=2;
443  ring r = 0, (c(1..2)), dp;
444  list l=c(1..2);
445  // Let c(1) be a variable of degree 1, let c(2) be a variable of degree 2.
446  // The monomials in c(1) and c(2) of weighted degree 5 are:
447  print( chNum( 5, l ) );
448
449  // Compare the result to the output of chNumbers(...):
450  print( chNumbers(5, l) );
451}
452//----------------------------------------------------------------------------------------
453
454proc chNumbers(int r, list c)
455"USAGE:   chNumbers(r, c);  r integer,  c list
456RETURN:   list
457PURPOSE:  computes the Chern numbers of a vector bundle with Chern classes c
458          on a complex manifold (variety) of dimension r
459EXAMPLE:  example chNumbers; shows an example
460NOTE:     computes basically the partitions of r
461"
462{
463  if(r<0)
464  {
465    print("The dimension of a manifold must be a non-negative integer!");
466    return(list()); // return the empty list in this case
467  }
468  if(r==0)
469  {
470    return(list(1));
471  }
472  //-----------------
473  // from now on r>0
474  //----------------
475  int n=size(c);
476  c=append_by_zeroes(r, c);
477  c=c[1..r]; // throw away redundant data
478  return(chNum(r, c));
479}
480example
481{
482  "EXAMPLE:";echo=2;
483  ring r = 0, (c(1..3)), dp;
484  list l=c(1..3);
485  // The Chern numbers of a vector bundle with Chern classes c(1), c(2), c(3)
486  // on a 3-fold:
487  print( chNumbers( 3, l ) );
488
489  // If the highest Chern class is zero, the Chern numbers are:
490  l=c(1..2);
491  print( chNumbers( 3, l ) );
492
493  // Compare this to the output of chNum(...):
494  print( chNum( 3, l ) );
495}
496//---------------------------------------------------------------------------------------
497
498proc sum_of_powers(int k, list l)
499"USAGE:   sum_of_powers(k, l);  k non-negative integer, l list of polynomials
500RETURN:   polynomial
501PURPOSE:  computes the sum of k-th powers of the entries of l
502EXAMPLE:  example sum_of_powers; shows an example
503NOTE:     returns 0 if k is negative
504"
505{
506  if(k<0) // return 0 if k is negative
507  {
508    print("The exponent must be non-negative; 0 has been returned");
509    return(0);
510  }
511  int i;
512  int n=size(l);
513  poly rez; // the result will be computed here
514  for(i=1;i<=n;i++) // compute the sum of powers
515  {
516    rez=rez+l[i]^k;
517  }
518  return(rez);
519}
520example
521{
522  "EXAMPLE:";echo =2;
523  ring r = 0, (x, y, z), dp;
524  list l=x, y, z;
525  //sum of 7-th powers of x, y, z
526  print( sum_of_powers(7, l) );
527}
528//-----------------------------------------------------------------------
529
530proc powSumSym(list c, list #)
531"USAGE:   powSumSym(l [,N]);  l a list of polynomials, N integer
532RETURN:   list of polynomials
533PURPOSE:  computes the expressions for the sums of powers [up to degree N]
534          in terms of the elementary symmetric polynomials (entries of l),
535EXAMPLE:  example powSumSym; shows an example
536NOTE:     returns the terms of the Chern character
537          multiplied by the corresponding factorials
538"
539{
540  int n;
541  if( size(#) == 0 ) // if there are no optional parameters
542  {
543    n = size(c); // set n to be the length of c
544  }
545  else // if there are optional parameters
546  {
547    if( is_integer(#[1])) // if the first optional parameter is an integer
548    {
549      n = max( #[1], 0 ); // if the parameter is negative, reset it to be zero
550      c = append_by_zeroes(n, c); // if n is greater than the length of c, append c by zeroes
551      if( n != 0 ) // if n is non-zero
552      {
553        c = c[1..n]; // take into account only the first n entries of c
554      }
555    }
556    else // if the optional parameter is not an integer, then
557    {
558      n=size(c); // ignore it and set n to be the length of c
559    }
560  }
561  list rez; // the result will be computed here
562  if(n==0) // return the empty list
563  {
564    return(rez)
565  }
566  else // otherwise proceed as follows:
567  {
568    // first compute the sums of powers of the Chern roots
569    // in terms of the Chern classes using the Newton's identities
570    int i, j, sign;
571    poly f;
572    // the first term of the Chern character coincides with the first Chern class,
573    // or equivalently with the sum of Chern roots
574    rez = rez + list(c[1]);
575    // compute the sums of powers of Chern roots recursively using the Newton's identities
576    for(j=2; j<=n; j++)
577    {
578      sign=1;
579      f=0;
580      for(i=1; i<j; i++)
581      {
582        f=f + c[i]*sign*rez[j-i];
583        sign = -sign;
584      }
585      f=f+sign*j*c[j];
586      rez=rez+list(f); // add the newly computed sum of powers of Chern roots to the list
587    }
588    return(rez); // return the result
589  }
590}
591example
592{
593  "EXAMPLE:";echo =2;
594  // the expressions of the first 3 sums of powers of 3 variables a(1), a(2), a(3)
595  // in terms of the elementary symmetric polynomials c(1), c(2), c(3):
596  ring r = 0, (c(1..3)), dp;
597  list l=(c(1..3));
598  print(powSumSym(l));
599  // The first 5 sums in the same situation
600  print(powSumSym(l, 5));
601}
602//---------------------------------------------------------------------------------
603
604proc chAll(list c, list #)
605"USAGE:   chAll(l [,N]);  l a list of polynomials, N integer
606RETURN:   list of polynomials
607PURPOSE:  computes the list of terms of positive degree [up to degree N] of
608          the Chern character, where the entries of l are considered as the Chern classes
609EXAMPLE:  example chAll; shows an example
610NOTE:     makes sense only for a list of polynomials
611"
612{
613    list rez; // to be the result
614    rez = powSumSym(c, #); // get the sums of powers of the Chern roots
615    int n = size(rez);
616    bigint fct=1;
617    int i;
618    for(i=1;i<=n;i++) // get the terms of the Chern character
619    {
620      fct=fct*i;
621      rez[i]=rez[i]/fct;
622    }
623    return(rez); // return the result
624}
625example
626{
627  "EXAMPLE:";echo =2;
628  // Chern character (terms of degree 1, 2, 3)
629  // corresponding to the Chern classes c(1), c(2), c(3):
630  ring r = 0, (c(1..3)), dp;
631  list l=(c(1..3));
632  print(chAll(l));
633  // terms up to degree 5 in the same situation
634  print(chAll(l, 5));
635}
636//---------------------------------------------------------------------------------
637
638proc chAllInv(list c)
639"USAGE:   chAllInv(l);  l a list of polynomials
640RETURN:   list of polynomials
641PURPOSE:  procedure inverse to chAll(), computes the list of Chern classes
642          from the list of terms of positive degree of the Chern character
643EXAMPLE:  example chAllInv; shows an example
644NOTE:     makes sense only for a list of polynomials
645"
646{
647  int n = size(c);
648  list rez;
649  if(n==0) // if the list of terms of Chern character is empty, return the empty list
650  {
651    return(rez);
652  }
653  else // otherwise compute the result using the Newton's identities
654  {
655    int j, i, sign;
656    poly f;
657    // transform the list of terms of the Chern character
658    // to the list of sums of powers of Chern roots
659    //bigint fct=1;
660    for(i=1; i<=n; i++)
661    {
662      //fct=fct*i;
663      //c[i]=fct*c[i];
664      c[i]=factorial(i)*c[i];
665    }
666    // the first Chern class coincides with the first degree term of the Chern character
667    rez=rez+list(c[1]);
668    // compute the higher Chern classes recursively using the Newton's identities
669    for(j=2;j<=n;j++)
670    {
671      sign=1;f=0;
672      for(i=1;i<j;i++)
673      {
674        f=f+ c[i]*sign*rez[j-i];
675        sign=-sign;
676      }
677      f=f+sign*c[j];
678      rez=rez+list(f/j);
679    }
680    return(rez); // return the result
681  }
682}
683example
684{
685  "EXAMPLE:";echo=2;
686  // first 3 Chern classes in terms of the first 3 terms
687  // of the Chern character Chern  ch(1), ch(2), ch(3):
688  ring r = 0, (ch(1..3)), dp;
689  list l=(ch(1..3));
690  print(chAllInv(l));
691  // let's see that chAllInv() is inverse to chAll()
692  print( chAll( chAllInv(l) ) );
693}
694//---------------------------------------------------------------------------------
695
696proc chHE(list c)
697"USAGE:   chHE(c);  c list of polynomials
698RETURN:   polynomial
699PURPOSE:  computes the highest relevant term of the Chern character
700EXAMPLE:  example chHE; shows an example
701NOTE:     uses the elimination and is extremely inefficient,
702          is included just for comparison with chAll(c)
703"
704{
705  int i;
706  // insure that the entries of c are polynomials
707  // in order to be able to apply maps
708  for(i=1;i<=size(c);i++)
709  {
710    c[i]=poly(c[i]);
711  }
712  int n=size(c);
713  if(n==0) // in this case return the empty list
714  {
715    return(list());
716  }
717  else // otherwise proceed as follows
718  {
719    def br@=basering; // remember the base ring
720    // add additional variables c@, a@(1..n) to the base ring
721    list l3 = "c@";
722    l3 = l3+ ringlist(basering)[2];
723    for (int ii = 1; ii <= n; ii++)
724    {
725     l3[size(l3)+1] = "a@("+string(ii)+")";
726    }
727    ring r@ = create_ring(ring_list(basering)[1], l3, "lp", "no_minpoly");
728    execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
729    list c=F(c); // embed c in the bigger ring
730    poly rez;
731    list A=a@(1..n);
732    list sym=symm(A);
733    ideal I;
734    poly E=1; // to be the product of variables which should be eliminated
735    for(i=1;i<=n;i++)
736    {
737      E=E*a@(i); // compute the product of the variables that must be eliminated
738      I=I, c[i]-sym[i];
739    }
740    I=I, c@-sum_of_powers(n, A);
741    I=simplify(elim(I, E),1);
742    rez = -subst(I[1], c@, 0);
743    setring br@; // come back to the initial base ring
744    execute( "map FF= r@,0,"+varstr(br@)+";" ); // define the specialization homomorphism
745    poly rez=FF(rez); // bring the result to the base ring
746    return( (1/factorial(n))*rez);
747  }
748}
749example
750{
751  "EXAMPLE:";echo =2;
752  ring r = 0, (c(1..3)), dp;
753  list l=c(1..3);
754  //the third degree term of the Chern character
755  print( chHE(l) );
756}
757//----------------------------------------------------------------------
758
759proc ChernRootsSum(list a, list b)
760"USAGE:   ChernRootsSum(a, b); a, b lists of polynomials
761RETURN:   list of polynomials
762PURPOSE:  computes the Chern roots of the direct (Whitney) sum
763          of a vector bundle with Chern roots a and a vector bundle with Chern roots b
764EXAMPLE:  example ChernRootsSum; shows an example
765NOTE:
766"
767{
768  return(a+b);
769}
770example
771{
772  "EXAMPLE:";echo =2;
773  ring r = 0, (a(1..3), b(1..2)), dp;
774  // assume a(1), a(2), a(3) are the Chern roots of a vector bundle E
775  // assume b(1), b(2) are the Chern roots of a vector bundle F
776  list l=a(1..3);
777  list L=b(1..2);
778  // the Chern roots of their direct sum is
779  print( ChernRootsSum(l, L) );
780}
781//----------------------------------------------------------------------
782
783proc chSum(list c, list C)
784"USAGE:   chSum(c, C);  c, C lists of polynomials
785RETURN:   list of polynomials
786PURPOSE:  computes the Chern classes of a direct sum of two vector bundles
787EXAMPLE:  example chSum; shows an example
788NOTE:
789"
790{
791  int N=size(c)+size(C);
792  c=append_by_zeroes(N, c); // append by zeroes if necessary
793  C=append_by_zeroes(N, C); // append by zeroes if necessary
794  list rez; // to be the result
795  int i;
796  int j;
797  poly f;
798  for(i=1;i<=N;i++)
799  {
800    f=c[i]+C[i];
801    for(j=1;j<i;j++)
802    {
803      f=f+c[j]*C[i-j];
804    }
805    rez=rez+list(f);
806  }
807  return(rez);
808}
809example
810{
811  "EXAMPLE:";echo =2;
812  ring r = 0, (c(1..3), C(1..2)), dp;
813  // Let E be a vector bundle with Chern classes c(1), c(2), c(3).
814  // Let F be a vector bundle with Chern classes C(1), C(2).
815  list l=c(1..3);
816  list L=C(1..2);
817  // Then the Chern classes of their direct sum are
818  print( chSum(l, L) );
819}
820//----------------------------------------------------------------------
821
822proc ChernRootsDual(list l)
823"USAGE:   ChernRootsDual(l); l a list of polynomials
824RETURN:   list of polynomials
825PURPOSE:  computes the Chern roots of the dual vector bundle
826          of a vector bundle with Chern roots from l
827EXAMPLE:  example ChernRootsDual; shows an example
828NOTE:
829"
830{
831  int n=size(l);
832  int i;
833  for(i=1;i<=n;i++) // change the sign of the entries of a
834  {
835    l[i]=-l[i];
836  }
837  return(l);
838}
839example
840{
841  "EXAMPLE:";echo =2;
842  ring r = 0, (a(1..3)), dp;
843  // assume a(1), a(2), a(3) are the Chern roots of a vector bundle
844  list l=a(1..3);
845  // the Chern roots of the dual vector bundle
846  print( ChernRootsDual(l) );
847}
848//----------------------------------------------------------------------
849
850proc chDual(list c)
851"USAGE:   chDual(c);   c list of polynomials
852RETURN:   list of polynomials
853PURPOSE:  computes the list of Chern classes of the dual vector bundle
854EXAMPLE:  example chDual; shows an example
855NOTE:
856"
857{
858  int n=size(c);
859  int i;
860  for(i=1;i<=n;i=i+2)
861  {
862    c[i]=-c[i];
863  }
864  return(c);
865}
866example
867{
868  "EXAMPLE:"; echo=2;
869  // Chern classes of a vector bundle that is dual to a vector bundle
870  // with Chern classes c(1), c(2), c(3)
871  ring r=0, (c(1..3)), dp;
872  list l=c(1..3);
873  print(chDual(l));
874}
875//-----------------------------------------------------------------------------------------
876
877proc ChernRootsProd(list a, list b)
878"USAGE:   ChernRootsProd(a, b); a, b lists of polynomials
879RETURN:   list of polynomials
880PURPOSE:  computes the Chern roots of the tensor product of a vector bundle with Chern roots a
881          and a vector bundles with Chern roots b
882EXAMPLE:  example ChernRootsProd; shows an example
883NOTE:
884"
885{
886  int na=size(a);
887  int nb=size(b);
888  int i;
889  int j;
890  list rez; // the result will be computed here
891  for(i=1;i<=na;i++) // compute the result
892  {
893    for(j=1;j<=nb;j++)
894    {
895      rez=rez+list(a[i]+b[j]);
896    }
897  }
898  return(rez);
899}
900example
901{
902  "EXAMPLE:"; echo=2;
903  ring r=0, (a(1..2), b(1..3)), dp;
904  list l=a(1..2);
905  list L=b(1..3);
906  // Chern roots of the tensor product of a vector bundle with Chern roots a(1), a(2)
907  // and a vector bundle with Chern roots b(1), b(2), b(3)
908  print(ChernRootsProd(l, L));
909}
910//-----------------------------------------------------------------------------------------
911
912proc chProd(def r,  list c, def R, list C, list #)
913"USAGE:   chProd(r, c, R, C [, N]);  r, R polynomials (integers);
914          c, C lists of polynomials, N integer
915RETURN:   list of polynomials
916PURPOSE:  computes the list of Chern classes of the product of two vector bundles
917          in terms of their ranks and Chern clases [up to degree N]
918EXAMPLE:  example chProd; shows an example
919NOTE:
920"
921{
922  // check the input data
923  if( is_integer(r) ) // if r is an integer
924  {
925    if(r<=0) // if r is negative or zero return the empty list
926    {
927      return( list() );
928    }
929    //----------------------------
930    //now r is a positive integer
931    //----------------------------
932    c=append_by_zeroes(r, c); // append c by zeroes if r is greater than the length of c
933    c=c[1..r]; // make c shorter (of length r) if r is smaller than the length of c
934  }
935  if( is_integer(R) ) // if R is an integer
936  {
937    if(R<=0) // if R is negative or zero return the empty list
938    {
939      return( list() );
940    }
941    //----------------------------
942    //now R is a positive integer
943    //----------------------------
944    C=append_by_zeroes(R, C); // append C by zeroes if R is greater than the length of C
945    C=C[1..R]; // make C shorter (of length R) if R is smaller than the length of C
946  }
947  //----------------------------------------------------------
948  //now r > 0 if it is an integer; R > 0 if it is an integer
949  //----------------------------------------------------------
950  int n;
951  if( is_integer(r) && is_integer(R) ) // if both r and R are integers
952  {
953    n=r*R; // set n to be the rank of the product bundle
954  }
955  else // otherwise define the rank of the product vector bundle by
956  {
957    n=size(c)*size(C); // looking at the lengths of c and C
958  }
959  if( size(#) != 0 ) // if there is an optional parameter
960  {
961    if( is_integer( #[1] )  ) // if this parameter is an integer
962    {
963      if( #[1]<=0 ) // if it is negative or zero, return the empty list
964      {
965        return( list() );
966      }
967      // now #[1] is positive
968      // the product bundle can only have non-zero Chern classes up to degree n
969      // so ignore the optional parameter if it is greater than n
970      n = min(#[1], n);
971    }
972  }
973  if(n==0) // if n is zero, return the empty list
974  {
975    return( list() );
976  }
977  //-----------------------------------------------------------
978  //now n is positive, we can perform the relevant computations
979  //-----------------------------------------------------------
980  int i, j;
981  c=append_by_zeroes(n, c); // append c by zeroes up to degree n
982  C=append_by_zeroes(n, C); // append C by zeroes up to degree n
983  c=c[1..n]; // throw away the redundant data if needed
984  C=C[1..n]; // throw away the redundant data if needed
985  // build the list of all terms of the Chern characters: for rank r, and Chern classes c
986  list ch = list(r) + chAll(c);
987  list CH = list(R) + chAll(C); // do the same for rank R and Chern classes C
988  poly f;
989  list chP;
990  // compute the list of the non-zero degree terms of the Chern character
991  // of the tensor product of two vector bundles
992  for(i=1;i<=n;i++) // using the multiplicativity of the Chern character
993  {
994    f=0;
995    for(j=0;j<=i;j++)
996    {
997      f=f+ch[j+1]*CH[i-j+1];
998    }
999    chP=chP+list(f);
1000  }
1001  return( chAllInv(chP) ); // return the corresponding Chern classes
1002}
1003example
1004{
1005  "EXAMPLE:"; echo =2;
1006  ring H = 0, ( r, R, c(1..3), C(1..2) ), dp;
1007  list l=c(1..3);
1008  list L=C(1..2);
1009  // the Chern classes of the tensor product of a vector bundle E of rank 3
1010  // with Chern classes c(1), c(2), c(3)
1011  // and a vector bundle F of rank 2 with Chern classes C(1) and C(2):
1012  print( chProd(3, l, 2, L) );
1013  // the first two Chern classes of the tensor product
1014  // of a vector bundle E of rank r with Chern classes c(1) and c(2)
1015  // and a vector bundle G of rank R with Chern classes C(1) and C(2)
1016  // this gives the Chern classes of a tensor product on a complex surface
1017  l=c(1..2);
1018  L=C(1..2);
1019  print( chProd(r, l, R, L, 2 ) );
1020}
1021//---------------------------------------------------------------------------------
1022
1023proc chProdE(list c, list C)
1024"USAGE:   chProdE(c, C);   c, C lists of polynomials
1025RETURN:   list of polynomials
1026PURPOSE:  computes the list of Chern classes of the product
1027          of two vector bundles in terms of their Chern clases
1028EXAMPLE:  example chProdE; shows an example
1029NOTE:     makes sense only for (lists of) polynomials;
1030          uses elimination, hence very inefficient;
1031          included only for comparison with chProd(...)
1032"
1033{
1034  int r=size(c);
1035  int R=size(C);
1036  // insure that the entries of c and C are polynomials
1037  // in order to be able to apply maps
1038  int i,j;
1039  for(i=1;i<=r;i++)
1040  {
1041    c[i]=poly(c[i]);
1042  }
1043  for(i=1;i<=R;i++)
1044  {
1045    C[i]=poly(C[i]);
1046  }
1047  if( (r==0) && (R==0) ) // if one of the ranks is 0,
1048  {
1049    return( list() ); // return the empty list (zero bundles have no Chern classes)
1050  }
1051  //------------------------------------
1052  //now both r and R are greater than 0
1053  //------------------------------------
1054  int n=r*R; // the rank of the product of two vector bundles
1055  def br@=basering; // remember the base ring
1056  // add additional variables a@(1..r), b@(1..R), x@ to the base ring
1057  int ii;
1058  list l4 = "x@";
1059  l4 = l4+ ringlist(basering)[2];
1060  for (ii = 1; ii <= r; ii++)
1061  {
1062   l4[size(l4)+1] = "a@("+string(ii)+")";
1063  }
1064  for (ii = 1; ii <= R; ii++)
1065  {
1066   l4[size(l4)+1] = "b@("+string(ii)+")";
1067  }
1068  ring r@ = create_ring(ring_list(basering)[1], l4, "lp", "no_minpoly");
1069  execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
1070  list c=F(c); // embed c in the bigger ring
1071  list C=F(C); // embed C in the bigger ring
1072  list A=a@(1..r); // list of Chern roots of the first vector bundle
1073  list syma = symm(A); // symmetric functions in the Chern roots of the first vector bundles
1074  list B=b@(1..R); // list of Chern roots of the second vector bundle
1075  list symb=symm(B); // symmetric functions in the Chern roots of the second vector bundles
1076  ideal I;
1077  // the product of variables (all Chern roots) which should be eliminated
1078  poly E=product(A)*product(B);
1079  for(i=1; i<=r; i++)
1080  {
1081    for(j=1; j<=R; j++)
1082    {
1083      I=I, c[i]-syma[i], C[j]-symb[j]; // add the relations
1084    }
1085  }
1086  // the Chern roots of the tensor product in terms of the Chern roots of the factors
1087  list crt=ChernRootsProd(A, B);
1088  list Cf=symm(crt); // Chern classes of the product in terms of the Chern roots of the factors
1089  list rez; // the result will be computed here
1090  ideal J;
1091  for(i=1;i<=n;i++)
1092  {
1093    J = I, x@-Cf[i]; // add the equation for the i-th Chern class to the ideal of relations
1094    J = simplify(elim(J, E), 1); // eliminate the Chern roots
1095    // get the expression for the i-th Chern class of the product
1096    // in terms of the Chern classes of the factors
1097    rez = rez + list( -subst(J[1], x@, 0) );
1098  }
1099  setring br@; // come back to the initial base ring
1100  execute( "map FF= r@, 0,"+varstr(br@)+";" ); // define the specialization homomorphism t@=0
1101  list rez=FF(rez); // bring the result to the base ring
1102  return(rez); // return the corresponding Chern classes
1103}
1104example
1105{
1106  "EXAMPLE:"; echo =2;
1107  ring H = 0, ( c(1..3), C(1..2) ), dp;
1108  list l=c(1..3);
1109  list L=C(1..2);
1110  // the Chern classes of the tensor product of a vector bundle E of rank 3
1111  // with Chern classes c(1), c(2), c(3)
1112  // and a vector bundle F of rank 2 with Chern classes C(1) and C(2):
1113  print( chProdE(l,  L) );
1114}
1115//------------------------------------------------------------------------------------
1116
1117proc chProdL(int r, list c, int R, list C)
1118"USAGE:   chProdL(r, c, R, C);  r, R integers; c, C lists of polynomials
1119RETURN:   list
1120PURPOSE:  computes the list of Chern classes of the product of two vector bundles
1121          in terms of their Chern clases
1122EXAMPLE:  example chProdL; shows an example
1123NOTE:     Implementation of the formula of Lascoux, the Schur polynomials are computed
1124          using the second Jacobi-Trudi formula (in terms of the Chern classes)
1125"
1126{
1127  // check the input data
1128  if(r<=0) // if r is negative or zero return the empty list
1129  {
1130    return( list() );
1131  }
1132  //----------------------------
1133  //now r is a positive integer
1134  //----------------------------
1135  c=append_by_zeroes(r, c); // append c by zeroes if r is greater than the length of c
1136  c=c[1..r]; // make c shorter (of length r) if r is smaller than the length of c
1137  if(R<=0) // if R is negative or zero return the empty list
1138  {
1139    return( list() );
1140  }
1141  //----------------------------
1142  //now R is a positive integer
1143  //----------------------------
1144  C=append_by_zeroes(R, C); // append C by zeroes if R is greater than the length of C
1145  C=C[1..R]; // make C shorter (of length R) if R is smaller than the length of C
1146  //----------------------------------------------------------
1147  // now r > 0 and R > 0
1148  //----------------------------------------------------------
1149  def br@=basering; // remember the base ring
1150  // add  additional variables to the base ring
1151  int ii;
1152  list l5 = ringlist(basering)[2];
1153  l5[size(l5)+1] = "t@";
1154  for (ii = 1; ii <= r; ii++)
1155  {
1156   l5[size(l5)+1] = "c@("+string(ii)+")";
1157  }
1158  for (ii = 1; ii <= R; ii++)
1159  {
1160   l5[size(l5)+1] = "C@("+string(ii)+")";
1161  }
1162  ring r@ = create_ring(ring_list(basering)[1], l5, "dp", "no_minpoly");
1163  execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
1164  list c, C;
1165  int i;
1166  for(i=1;i<=r;i++)
1167  {
1168    c[i]=c@(i)*t@^i;
1169  }
1170  for(i=1;i<=R;i++)
1171  {
1172    C[i]=C@(i)*t@^i;
1173  }
1174  poly f = chProdLP(r,c,R,C); // get the total Chern class using the Lascoux formula
1175  matrix CF = coeffs(f, t@); // get its coefficients in front of the powers of t@
1176  int N=r*R;
1177  list rez; // write them in a list
1178  for(i=1;i<=N;i++)
1179  {
1180    rez=rez+list(CF[i+1,1]);
1181  }
1182  setring br@; // come back to the initial base ring
1183  // define the specialization homomorphism
1184  execute("map FF = r@,"+varstr(br@)+",0, c[1..r], C[1..R];");
1185  return( FF( rez ) ); // bring the result to the initial ring
1186}
1187example
1188{
1189  "EXAMPLE:"; echo =2;
1190  // The Chern classes of the tensor product of a vector bundle of rank 3
1191  // with Chern classes c(1), c(2), c(3) and a vector bundle of rank 1 with
1192  // Chern class C(1)
1193  ring r = 0, ( c(1..3), C(1)), dp;
1194  list c=c(1..3);
1195  list C=C(1);
1196  print( chProdL(3,c,1,C) );
1197}
1198//---------------------------------------------------------------------------------------
1199
1200proc chProdLP(int r, list c, int R, list C)
1201"USAGE:   chProdLP(r, c, R, C);  r, R integers; c, C lists of polynomials
1202RETURN:   polynomial
1203PURPOSE:  computes the total Chern class of the product of two vector bundles
1204          in terms of their ranks and Chern clases
1205EXAMPLE:  example chProdLP; shows an example
1206NOTE:     Implementation of the formula of Lascoux, the Schur polynomials are computed
1207          using the second Jacobi-Trudi formula (in terms of the Chern classes)
1208"
1209{
1210  if(r<=0) // if r is negative or zero, return 1
1211  {
1212    return( 1 );
1213  }
1214  if(R<=0) // if R is negative or zero, return 1
1215  {
1216    return( 1 );
1217  }
1218  //-------------------------------------------
1219  // now r and R are positive
1220  //-------------------------------------------
1221  c=append_by_zeroes(r, c);
1222  C=append_by_zeroes(R, C);
1223  c=c[1..r];
1224  C=C[1..R];
1225  list P;
1226  P=part(r, R); // compute the partitions of numbers up to R into r summands
1227  int sz=size(P); // number of such partitions
1228  int szu;
1229  int i, j;
1230  list T;
1231  list PU;
1232  list TU;
1233  poly rez; // the result will be computed here
1234  poly ST;
1235  // implement the formula of Lascoux:
1236  for(i=1;i<=sz;i++) // run through all the partitions from P
1237  {
1238    T=P[i]; // the current partition
1239    ST= SchurS( PartC(T, R) , C ); // compute the corresponding Schur polynomial
1240    PU=partUnder(T); // compute the partitions under T
1241    szu=size(PU); // number of such partitions
1242    for(j=1;j<=szu;j++) // run through all the partitions lying under T
1243    {
1244      TU=PU[j]; // for each of them
1245      rez=rez+IJcoef(T, TU)* SchurCh(TU, c) *ST; // add the corresponding term to the result
1246     }
1247  }
1248  return(rez); // return the result
1249}
1250example
1251{
1252  "EXAMPLE:"; echo =2;
1253  // The total Chern class of the tensor product of a vector bundle of rank 3
1254  // with Chern classes c(1), c(2), c(3) and a vector bundle of rank 1 with
1255  // Chern class C(1)
1256  ring r = 0, ( c(1..3), C(1)), ws(1,2,3, 1);
1257  list c=c(1..3);
1258  list C=C(1);
1259  print( chProdLP(3,c,1,C) );
1260}
1261//---------------------------------------------------------------------------------------
1262
1263proc chProdM(int r, list c, int R, list C)
1264"USAGE:   chProdM(r, c, R, C);  r, R integers; c, C lists of polynomials
1265RETURN:   list
1266PURPOSE:  computes the list of Chern classes of the product of two vector bundles
1267          in terms of their Chern clases
1268EXAMPLE:  example chProdM; shows an example
1269NOTE:     Implementation of the formula of Manivel
1270"
1271{
1272  // check the input data
1273  if(r<=0) // if r is negative or zero return the empty list
1274  {
1275    return( list() );
1276  }
1277  //----------------------------
1278  //now r is a positive integer
1279  //----------------------------
1280  c=append_by_zeroes(r, c); // append c by zeroes if r is greater than the length of c
1281  c=c[1..r]; // make c shorter (of length r) if r is smaller than the length of c
1282  if(R<=0) // if R is negative or zero return the empty list
1283  {
1284    return( list() );
1285  }
1286  //----------------------------
1287  //now R is a positive integer
1288  //----------------------------
1289  C=append_by_zeroes(R, C); // append C by zeroes if R is greater than the length of C
1290  C=C[1..R]; // make C shorter (of length R) if R is smaller than the length of C
1291  //----------------------------------------------------------
1292  // now r > 0 and R > 0
1293  //----------------------------------------------------------
1294  def br@=basering; // remember the base ring
1295  // add  additional variables to the base ring
1296  int ii;
1297  list l6 = ringlist(basering)[2];
1298  l6[size(l6)+1] = "t@";
1299  for (ii = 1; ii <= r; ii++)
1300  {
1301   l6[size(l6)+1] = "c@("+string(ii)+")";
1302  }
1303  for (ii = 1; ii <= R; ii++)
1304  {
1305   l6[size(l6)+1] = "C@("+string(ii)+")";
1306  }
1307  ring r@ = create_ring(ring_list(basering)[1], l6, "dp", "no_minpoly");
1308  execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
1309  list c, C;
1310  int i;
1311  for(i=1;i<=r;i++)
1312  {
1313    c[i]=c@(i)*t@^i;
1314  }
1315  for(i=1;i<=R;i++)
1316  {
1317    C[i]=C@(i)*t@^i;
1318  }
1319  poly f = chProdMP(r,c,R,C); // get the total Chern class using the Manivel formula
1320  matrix CF = coeffs(f, t@); // get its coefficients in front of the powers of t@
1321  int N=r*R;
1322  list rez; // write them in a list
1323  for(i=1;i<=N;i++)
1324  {
1325    rez=rez+list(CF[i+1,1]);
1326  }
1327  setring br@; // come back to the initial base ring
1328  // define the specialization homomorphism
1329  execute("map FF = r@,"+varstr(br@)+",0, c[1..r], C[1..R];");
1330  return( FF( rez ) ); // bring the result to the initial ring
1331}
1332example
1333{
1334  "EXAMPLE:"; echo = 2;
1335  // The Chern classes of the tensor product of a vector bundle of rank 3
1336  // with Chern classes c(1), c(2), c(3) and a vector bundle of rank 1 with
1337  // Chern class C(1)
1338  ring r = 0, ( c(1..3), C(1)), dp;
1339  list c=c(1..3);
1340  list C=C(1);
1341  print( chProdM(3,c,1,C) );
1342}
1343//---------------------------------------------------------------------------------------
1344
1345proc chProdMP(int r, list c, int R, list C)
1346"USAGE:   chProdMP(r, c, R, C);  r, R integers; c, C lists of polynomials
1347RETURN:   polynomial
1348PURPOSE:  computes the total Chern class of the product of two vector bundles
1349          in terms of their ranks and Chern clases
1350EXAMPLE:  example chProdMP; shows an example
1351NOTE:     Implementation of the formula of Lascoux, the Schur polynomials are computed
1352          using the second Jacobi-Trudi formula (in terms of the Chern classes)
1353"
1354{
1355  if(r<=0) // if r is negative or zero, return 1
1356  {
1357    return( 1 );
1358  }
1359  if(R<=0) // if R is negative or zero, return 1
1360  {
1361    return( 1 );
1362  }
1363  //-------------------------------------------
1364  // now r and R are positive
1365  //-------------------------------------------
1366  c=append_by_zeroes(r, c);
1367  C=append_by_zeroes(R, C);
1368  c=c[1..r];
1369  C=C[1..R];
1370  list P;
1371  P=part(r, R); // compute the partitions of numbers up to R into r summands
1372  int sz=size(P); // number of such partitions
1373  int szu;
1374  int i, j;
1375  list T;
1376  list PU;
1377  list TU;
1378  poly rez; // the result will be computed here
1379  poly ST;
1380  // implement the formula of Manivel:
1381  for(i=1;i<=sz;i++) // run through all the partitions from P
1382  {
1383    T=P[i]; // the current partition
1384    ST= SchurS( PartC(T, R) , C ); // compute the corresponding Schur polynomial
1385    PU=partUnder(T); // compute the partitions under T
1386    szu=size(PU); // number of such partitions
1387    for(j=1;j<=szu;j++) // run through all the partitions lying under T
1388    {
1389      TU=PU[j]; // for each of them
1390      // add the corresponding term to the result
1391      rez=rez+Pcoef( TU, PartC(dualPart(T, R), r), r, R )* SchurCh(TU, c) *ST;
1392    }
1393  }
1394  return(rez); // return the result
1395}
1396example
1397{
1398  "EXAMPLE:"; echo =2;
1399  // The total Chern class of the tensor product of a vector bundle of rank 3
1400  // with Chern classes c(1), c(2), c(3) and a vector bundle of rank 1 with
1401  // Chern class C(1)
1402  ring r = 0, ( c(1..3), C(1)), ws(1,2,3, 1);
1403  list c=c(1..3);
1404  list C=C(1);
1405  print( chProdMP(3,c,1,C) );
1406}
1407//---------------------------------------------------------------------------------------
1408
1409proc ChernRootsHom(list a, list b)
1410"USAGE:   ChernRootsHom(a, b); a, b lists of polynomials
1411RETURN:   list of polynomials
1412PURPOSE:  for a vector bundle E with Chern roots a and a vector bundle F
1413          with Chern roots b, computes the Chern roots of Hom(E, F)
1414EXAMPLE:  example ChernRootsHom; shows an example
1415NOTE:
1416"
1417{
1418  int na=size(a);
1419  int nb=size(b);
1420  int i;
1421  int j;
1422  list rez; // the result will be computed here
1423  for(i=1;i<=na;i++) // compute the result
1424  {
1425    for(j=1;j<=nb;j++)
1426    {
1427      rez=rez+list(-a[i]+b[j]);
1428    }
1429  }
1430  return(rez);
1431}
1432example
1433{
1434  "EXAMPLE:"; echo=2;
1435  ring r=0, (a(1..2), b(1..3)), dp;
1436  list l=a(1..2);
1437  list L=b(1..3);
1438  // Let E be a vector bundle with Chern roots a(1). a(2),
1439  // let F be a vector bundle with CHern roots b(1), b(2), b(3).
1440  // Then the Chern roots of Hom(E, F) are
1441  print(ChernRootsHom(l, L));
1442}
1443//-----------------------------------------------------------------------------------------
1444
1445proc chHom(def r,  list c, def R, list C, list #)
1446"USAGE:   chHom(r, c, R, C [, N]);  r, R polynomials (integers);
1447          c, C lists of polynomials, N integer
1448RETURN:   list of polynomials
1449PURPOSE:  computes [up to degree N] the list of Chern classes of the vector bundle Hom(E, F)
1450          in terms of the ranks and the Chern classes of E and F
1451EXAMPLE:  example chHom; shows an example
1452NOTE:
1453"
1454{
1455  return( chProd(r, chDual(c), R, C, # ) );
1456}
1457example
1458{
1459  "EXAMPLE:"; echo=2;
1460  ring H = 0, ( r, R, c(1..3), C(1..2) ), dp;
1461  list l=c(1..3);
1462  list L=C(1..2);
1463  // the Chern classes of Hom(E, F) for a vector bundle E of rank 3
1464  // with Chern classes c(1), c(2), c(3)
1465  // and a vector bundle F of rank 2 with Chern classes C(1) and C(2):
1466  print( chHom(3, l, 2, L) );
1467  // the first two Chern classes of Hom(E, F) for a vector bundle E of rank r
1468  // with Chern classes c(1) and c(2)
1469  // and a vector bundle G of rank R with Chern classes C(1) and C(2)
1470  // this gives the Chern classes of a tensor product on a complex surface
1471  l=c(1..2);
1472  L=C(1..2);
1473  print( chHom(r, l, R, L, 2 ) );
1474}
1475//---------------------------------------------------------------------------------
1476
1477proc ChernRootsSymm(int n, list l)
1478"USAGE:   ChernRootsSymm(m, l); m integer, l a list of polynomials
1479RETURN:   list of polynomials
1480PURPOSE:  computes the Chern roots of m-th symmetric power
1481          of a vector bundle with Chern roots from l
1482EXAMPLE:  example ChernRootsSymm; shows an example
1483NOTE:
1484"
1485{
1486  if(n<0) // return the empty list if n is negative
1487  {
1488    return(list(0));
1489  }
1490  int r=size(l);
1491  def br@=basering; // remember the base ring
1492  ring r@=0, (a@(1..r)), dp;
1493  ideal mon = a@(1..r);
1494  mon=mon^n; // all monomials of degree n
1495  list rez;
1496  int i, j;
1497  int N = size(mon);
1498  intvec v;
1499  for(i=1; i<=N; i++) // collect in rez the exponents of the monomials of degree n
1500  {
1501    v = leadexp(mon[i]);
1502    rez = rez + list(v);
1503  }
1504  setring br@;
1505  poly f;
1506  list rez1;
1507  // run over all exponents and construct the corresponding sums of the Chern roots
1508  for(i=1; i<=N; i++)
1509  {
1510    f=0;
1511    for(j=1;j<=r;j++)
1512    {
1513      f=f+rez[i][j]*l[j];
1514    }
1515    rez1=rez1+list(f);
1516  }
1517  return(rez1);
1518}
1519example
1520{
1521  "EXAMPLE:";echo =2;
1522  ring r=0, (a(1..3)), dp;
1523  list l=a(1..3);
1524  // the Chern roots of the second symmetric power of a vector bundle
1525  // with Chern  roots a(1), a(2), a(3)
1526  print( ChernRootsSymm(2, l) );
1527}
1528//------------------------------------------------------------
1529
1530proc ChernRootsWedge( int m, list l)
1531"USAGE:   ChernRootsWedge(m, l); m integer, l a list of polynomials
1532RETURN:   list of polynomials
1533PURPOSE:  computes the Chern roots of m-th exterior power
1534          of a vector bundle with Chern roots from l
1535EXAMPLE:  example ChernRootsWedge; shows an example
1536NOTE:     makes sense only for list of polynomials
1537"
1538{
1539  int n=size(l);
1540  if((m>n)||(m<=0) ) // if m is bigger that n or non-positive
1541  {
1542    return( list(0) ); // return the list with one zero entry
1543  }
1544  else
1545  {
1546    if(m==n) // if m equals n, the only Chern root of the exterior power will be
1547    {
1548      return( list(sum(l)) ); // the sum of the initial Chern roots
1549    }
1550    else // otherwise proceed recursively
1551    {
1552      int i;
1553      list rez;
1554      list rez1;
1555      list l1 = delete(l, 1); // throw away the first element from the list
1556      poly f = l[1]; // remember the first entry of l
1557      // compute the Chern roots of the (m-1)-th exterior power of the smaller list
1558      rez1 = ChernRootsWedge(m-1, l1 );
1559      int s = size( rez1 );
1560      // add the first entry of the bigger list to every entry in the result,
1561      // this will give all Chern roots involving f
1562      for(i=1; i<=s; i++)
1563      {
1564        rez1[i] = f+rez1[i];
1565      }
1566      // return the union of those Chern roots with f and those without f
1567      rez = ChernRootsWedge(m, l1) + rez1;
1568      return( rez );
1569    }
1570  }
1571}
1572example
1573{
1574  "EXAMPLE:";echo =2;
1575  ring r=0, (a(1..3)), dp;
1576  list l=a(1..3);
1577  // the Chern roots of the second exterior power of a vector bundle
1578  // with Chern  roots a(1), a(2), a(3)
1579  print( ChernRootsWedge(2, l) );
1580}
1581//---------------------------------------------------------------------------------
1582
1583proc chSymm(int k, int r, list c, list #)
1584"USAGE:   chSymm(k, r, c[, pos]);  k, r integers, c list of polynomials, pos list of integers
1585RETURN:   list with entries: int N, list of polynomials l
1586PURPOSE:  computes the rank and the Chern classes of the symmetric power of a vector bundle
1587EXAMPLE:  example chSymm; shows an example
1588NOTE:     for the second symmetric power chSymm2L(...) could be faster
1589"
1590{
1591  // insure that the entries of c are polynomials
1592  // in order to be able to apply maps
1593  int i;
1594  for(i=1;i<=size(c);i++)
1595  {
1596    c[i]=poly(c[i]);
1597  }
1598  if(r<0) // if the rank is negative
1599  {
1600    print("The rank of a vector bundle can non be negative");
1601    return(list()); // return the empty list in this case
1602  }
1603  if(r==0) // if we deal with the zero bundle
1604  {
1605    return( list( 0, list() ) ); // return the data corresponding to the zero bundle
1606  }
1607  //-----------------------------------
1608  // from now on we are in the case r>0
1609  //-----------------------------------
1610  // if the length  n of the list of Chern classes is smaller
1611  // than the rank of the vector bundle,
1612  // the higher classes are assumed to be zero and the list is appended by zeroes up to length r
1613  c=append_by_zeroes(r, c);
1614  // if the length of the list of the Chern classes is greater than the rank
1615    c=c[1..r]; // throw away the redundant data
1616  //-----------------------------------
1617  // from now on the length of c is r>0
1618  //-----------------------------------
1619  if(k<0)
1620  {
1621    print("You are trying to compute a negative symmetric power of a vector bundle");
1622    return( list(0, list() ) ); // assume such a power to be just a zero bundle
1623  }
1624  if(k==0) // the zeroth symmetric power is the trivial line bundle
1625  {
1626    return( list(1, list(0)) );
1627  }
1628  if(k==1) // the first symmetric power is equal to the vector bundle itself
1629  {
1630    return(list(r, c));
1631  }
1632  //-----------------------------------
1633  // from now on we are in the case k>2
1634  //-----------------------------------
1635  list LM = integer_list(#);
1636  int M = LM[2]; // maximum among the optional parameters
1637  # = LM[1]; // take into account only the first integer optional parameters that are positive
1638  //-------------------------------
1639  // Perform the computations now
1640  //-------------------------------
1641  def br@=basering; // remember the base ring
1642  // add additional variables to the base ring
1643  int ii;
1644  list l7 = "x@";
1645  l7 = l7+ ringlist(basering)[2];
1646  for (ii = 1; ii <= r; ii++)
1647  {
1648   l7[size(l7)+1] = "a@("+string(ii)+")";
1649  }
1650  ring r@ = create_ring(ring_list(basering)[1], l7, "lp", "no_minpoly");
1651  execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
1652  list c=F(c); // embed c into the bigger ring
1653  list rez; // the Chern classes of the symmetric power are going to be written here
1654  poly E = product( list( a@(1..r ) )  ); // product of the Chern roots
1655  list ss=ChernRootsSymm(k, list( a@(1..r) ) ); // list of the Chern roots of the symmetric power
1656  int N=size(ss); // number of such roots, it equals the rank of the symmetric power
1657  // the entries in C will be the Chern classes of the symmetric power
1658  // expressed in terms of the Chern roots of the initial vector bundle
1659  list C;
1660  ideal I, J;
1661  // list of the Chern classes of the initial vector bundle expressed in its Chern roots
1662  list sym=symm(list(a@(1..r)));
1663  if(size(#)==0) // if there are no optional parameters, compute all Chern classes
1664  {
1665    // the entries here are the Chern classes of the symmetric power
1666    // expressed in terms of Chern roots of the initial vector bundle
1667    C=symm(ss);
1668    for(i=1;i<=N;i++) // eliminate the Chern roots
1669    {
1670      if(i<= r) // first add all relevant  formulas for the Chern classes in terms of Chern roots
1671      {
1672        I=I, c[i]-sym[i];
1673      }
1674      J = I,  x@-C[i];
1675      // Notice that elim(...) is from the library "elim.lib",
1676      // it is loaded as a result of loading "general.lib"
1677      J=simplify(elim(J, E), 1);
1678      // get the expression of the next Chern class
1679      // in terms of the Chern classes of the initial vector bundle
1680      rez=rez+list( -subst(  J[1], x@, 0)  );
1681    }
1682  }
1683  else // otherwise compute only the needed Chern classes
1684  {
1685    C=symm(ss, M); // only the needed Chern classes
1686    int j;
1687    i=1;
1688    // the maximal number of optional parameters to be considered does not exceed N,
1689    // i.e., the rank of the symmetric power
1690    int NN = min( size(#), N);
1691    for(j=1; j <= NN; j++) // process the optional parameters
1692    {
1693      // process the optional parameters only until they are not bigger than N;
1694      // notice they are positive anyway after integer_list(...)
1695      if( #[j]<=N  )
1696      {
1697        for( ; i<=#[j];i++)
1698        {
1699          if(i<=r)
1700          {
1701            // add the relevant formulas for the Chern classes in terms of the Chern roots
1702            I=I, c[i]-sym[i];
1703          }
1704        }
1705        J= I, x@-C[ #[j]];
1706        // Notice that elim(...) is from the library "elim.lib",
1707        // it is loaded as a result of loading "general.lib"
1708        J=simplify(elim(J, E), 1);
1709        // get the expression of the next Chern class
1710        // in terms of the Chern classes of the initial vector bundle
1711        rez=rez+list( -subst(  J[1], x@, 0)  );
1712      }
1713      else // get out from the loop
1714      {
1715        break;
1716      }
1717    }
1718  }
1719  // used because Singular seems not to be able to apply maps to empty lists (see below)
1720  if(size(rez)==0)
1721  {
1722    return(list(N, list()));
1723  }
1724  setring br@; // come back to the initial base ring
1725  // define the specialization homomorphism,
1726  // evaluate the formulas for the Chern classes on their given values
1727  execute( "map FF = r@,0,"+varstr(br@)+";" );
1728  list rez=FF( rez ); // bring the result back to the initial ring
1729  return( list( N, rez  ) ); // return the result together with the rank of the symmetric power
1730}
1731example
1732{
1733  "EXAMPLE:";echo =2;
1734  ring r=0, (c(1..5)), dp;
1735  list l=c(1..5);
1736  // the rank and the Chern classes of the second symmetric power of a vector bundle of rank 3
1737  print( chSymm(2, 3, l) );
1738  // the rank and the first 3 Chern classes
1739  // of the second symmetric power of a vector bundle of rank 5
1740  print( chSymm(2, 5, l, 1, 2, 3) );
1741}
1742//----------------------------------------------------------------------------------
1743
1744proc chSymm2L(int r, list c)
1745"USAGE:   chSymm2L(r, c); r integer, c list of polynomials
1746RETURN:   list of polynomials
1747PURPOSE:  computes the Chern classes of the second symmetric power of a vector bundle
1748EXAMPLE:  example chSymm2L; shows an example
1749NOTE:     Implementation of the formula of Lascoux, the Schur polynomials are computed
1750          using the second Jacobi-Trudi formula (in terms of the Chern classes)
1751"
1752{
1753  // insure that the entries of c are polynomials
1754  // in order to be able to apply maps
1755  int i;
1756  for(i=1;i<=size(c);i++)
1757  {
1758    c[i]=poly(c[i]);
1759  }
1760  if(r<0) // if the rank is negative
1761  {
1762    print("The rank of a vector bundle can non be negative");
1763    return(list()); // return the empty list in this case
1764  }
1765  if(r==0) // if we deal with the zero bundle
1766  {
1767    return( list( 0, list() ) ); // return the data corresponding to the zero bundle
1768  }
1769  //-----------------------------------
1770  // from now on we are in the case r>0
1771  //-----------------------------------
1772  c=append_by_zeroes(r, c);
1773  c=c[1..r];
1774  def br@=basering; // remember the base ring
1775  // add  additional variables to the base ring
1776  list l8 = ringlist(basering)[2];
1777  l8[size(l8)+1] = "t@";
1778  for (int ii = 1; ii <= r; ii++)
1779  {
1780   l8[size(l8)+1] = "c@("+string(ii)+")";
1781  }
1782  ring r@ = create_ring(ring_list(basering)[1], l8, "dp", "no_minpoly");
1783  execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
1784  list c;
1785  for(i=1;i<=r;i++)
1786  {
1787    c[i]=c@(i)*t@^i;
1788  }
1789  poly f = chSymm2LP(r,c); // get the total Chern class using the formula of Lascoux
1790  matrix CF = coeffs(f, t@);
1791  int N=r*(r+1) div 2;
1792  list rez; // write the coefficients in front of the powers of t@ into a list
1793  for(i=1;i<=N;i++)
1794  {
1795    rez=rez+list(CF[i+1,1]);
1796  }
1797  setring br@; // come back to the initial base ring
1798  execute("map FF = r@,"+varstr(br@)+",0, c[1..r];"); // define the specialization homomorphism
1799  return( list(N, FF( rez )) ); // bring the result to the initial ring
1800}
1801example
1802{
1803  "EXAMPLE:";echo =2;
1804  ring r=0, (c(1..2)), dp;
1805  list l=c(1..2);
1806  // the Chern classes of the second symmetric power of a vector bundle of rank 2
1807  print( chSymm2L(2, l));
1808}
1809//---------------------------------------------------------------------------------------
1810
1811proc chSymm2LP(int r, list c)
1812"USAGE:   chSymm2LP(r, c); r integer, c list of polynomials
1813RETURN:   poly
1814PURPOSE:  computes the total Chern class of the second symmetric power of a vector bundle
1815EXAMPLE:  example chSymm2LP; shows an example
1816NOTE:     Implementation of the formula of Lascoux, the Schur polynomials are computed
1817          using the second Jacobi-Trudi formula (in terms of the Chern classes)
1818"
1819{
1820  if(r<0) // if the rank is negative
1821  {
1822    print("The rank of a vector bundle can non be negative");
1823    return(1); // return 1 in this case
1824  }
1825  if(r==0) // if we deal with the zero bundle
1826  {
1827    return( 1 ); // return 1 in this case
1828  }
1829  //-------------------------------------------
1830  // from now on we are in the case r > 0
1831  //-------------------------------------------
1832  c=append_by_zeroes(r, c);
1833  c=c[1..r];
1834  list I; // the partition (1,2,...,r) will be stored here
1835  int i;
1836  for(i=1;i<=r;i++)
1837  {
1838    I=I+list(i);
1839  }
1840  list PU = partUnder(I); // compute the partitions under I
1841  int sz=size(PU); // get their number
1842  poly rez; // the result will be computed here
1843  list J;
1844  poly cf;
1845  int ex;
1846  // implement the formula of Lascoux
1847  for(i=1;i<=sz;i++)
1848  {
1849    J=PU[i];
1850    ex=sum(J)- r*(r-1) div 2;
1851    if(ex>=0)
1852    {
1853      cf=bigint(2)^ex*IJcoef(I, J);
1854    }
1855    else
1856    {
1857      cf=IJcoef(I, J)/bigint(2)^(-ex);
1858    }
1859    rez = rez + cf * SchurCh(J, c );
1860  }
1861  return(rez);
1862}
1863example
1864{
1865  "EXAMPLE:";echo =2;
1866  ring r=0, (c(1..2)), ws(1, 2);
1867  list l=c(1..2);
1868  // the total Chern class of the second symmetric power of a vector bundle of rank 2
1869  print( chSymm2LP(2, l));
1870}
1871//---------------------------------------------------------------------------------------
1872
1873proc chWedge(int k, int r, list c, list #)
1874"USAGE:   chWedge(k, r, c [,pos]);  k, r integers, c list of polynomials, pos list of integers
1875RETURN:   list with entries: int N, list of polynomials l
1876PURPOSE:  computes the rank and the Chern classes of the exterior power of a vector bundle
1877EXAMPLE:  example chWedge; shows an example
1878NOTE:     for the second exterior power chWedge2L(...) could be faster
1879"
1880{
1881  // insure that the entries of c are polynomials
1882  // in order to be able to apply maps
1883  int i;
1884  for(i=1;i<=size(c);i++)
1885  {
1886    c[i]=poly(c[i]);
1887  }
1888  if(r<0) // if the rank is negative
1889  {
1890    print("The rank of a vector bundle can non be negative");
1891    return(list()); // return the empty list in this case
1892  }
1893  if(r==0) // if we deal with the zero bundle
1894  {
1895    return( list( 0, list() ) ); // return the data corresponding to the zero bundle
1896  }
1897  //-------------------------------------------
1898  // from now on we are in the case r > 0
1899  //-------------------------------------------
1900  if(k<0)
1901  {
1902    print("You are trying to compute a negative exterior power of a vector bundle");
1903    return( list(0, list() ) ); // assume such a power to be just a zero bundle
1904  }
1905  if(k==0) // the zeroth exterior power is the trivial line bundle
1906  {
1907    return( list(1, list(0)) );
1908  }
1909  if(k==1) // the first exterior power is equal to the vector bundle itself
1910  {
1911    c=append_by_zeroes(r, c);
1912    c=c[1..r];
1913    return(list(r, c));
1914  }
1915  //---------------------------------------
1916  // from now on we are in the case k > 2
1917  //---------------------------------------
1918  // if the length of the list of Chern classes is smaller than the rank of the vector bundle,
1919  // the higher classes are assumed to be zero and the list is appended by zeroes up to length r
1920  c=append_by_zeroes(r, c);
1921  // if the length of the list of the Chern classes is greater than the rank
1922    c=c[1..r]; // throw away the redundant data
1923  //------------------------------------------
1924  // from now on the length of c is r > 0
1925  //------------------------------------------
1926  if( k>r ) // if k>r, the exterior power is zero
1927  {
1928    return( list( int(0), list()  ) );
1929  }
1930  //-----------------------------------------------
1931  // from now on we are in the case 0 < k <= r = n
1932  //-----------------------------------------------
1933  if(k==r)
1934  {
1935    return(list( int(1), list( c(1) ) ) );
1936  }
1937  //-----------------------------------------------
1938  // from now on we are in the case 0 < k < r = n
1939  //-----------------------------------------------
1940  list LM = integer_list(#);
1941  int M=LM[2]; // maximum among the optional parameters if there are any, zero otherwise
1942  # = LM[1]; // take into account only the first integer optional parameters that are positive
1943  //-----------------------------
1944  // Let us compute now
1945  //-----------------------------
1946  def br@=basering; // remember the base ring
1947  // add additional variables a@(1..r), x@ to the base ring
1948  list l9 = "x@";
1949  l9 = l9+ ringlist(basering)[2];
1950  for (int ii = 1; ii <= r; ii++)
1951  {
1952   l9[size(l9)+1] = "a@("+string(ii)+")";
1953  }
1954  ring r@ = create_ring(ring_list(basering)[1], l9, "lp", "no_minpoly");
1955  execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
1956  list c = F(c); // embed c into the bigger ring
1957  list rez; // the result should be computed here
1958  poly E = product( list( a@(1..r ) )  ); // product of the Chern roots to be eliminaned
1959  list ss=ChernRootsWedge(k,  list( a@(1..r) )); // list of the Chern roots of the exterior product
1960  int N=size(ss); // length of ss, equals the rank of the exterior product
1961  // list of the Chern classes of the initial vector bundle in terms of their Chern roots
1962  list sym=symm(list(a@(1..r)));
1963  // the entries here will be the Chern classes we need
1964  // expressed in  terms of the Chern roots of the initial vector bundle
1965  list C;
1966  ideal I, J;
1967  if( size(#) == 0 ) // if there are no optional parameters, compute all Chern classes
1968  {
1969    // the entries here are the Chern classes we need
1970    // expressed in  terms of the Chern roots of the initial vector bundle
1971    C=symm(ss);
1972    for(i=1;i<=N;i++) // eliminate the Chern roots
1973    {
1974      if(i<= r) // first add all relevant  formulas for the Chern classes in terms of Chern roots
1975      {
1976        I=I, c[i]-sym[i];
1977      }
1978      J = I,  x@-C[i];
1979      // Notice that elim(...) is from the library "elim.lib",
1980      // it is loaded as a result of loading "general.lib"
1981      J=simplify(elim(J, E), 1);
1982      // get the expression of the next Chern class
1983      // in terms of the Chern classes of the initial vector bundle
1984      rez=rez+list( -subst(  J[1], x@, 0)  );
1985    }
1986  }
1987  else // otherwise compute only the needed Chern classes
1988  {
1989    // the entries here are the Chern classes we need
1990    // expressed in  terms of the Chern roots of the initial vector bundle
1991    C=symm(ss, M);
1992    int j;
1993    i=1;
1994    // the maximal number of optional parameters to be considered
1995    // does not exceed N, the rank of the exterior power
1996    int NN = min( size(#), N);
1997    for(j=1; j <= NN; j++) // process the optional parameters
1998    {
1999      // process the optional parameters only until they are not bigger than N;
2000      // notice they are positive anyway after integer_list(...)
2001      if( #[j]<=N  )
2002      {
2003        for( ; i<=#[j]; i++)
2004        {
2005          if( i<=r )
2006          {
2007            // add the relevant formulas for the Chern classes in terms of the Chern roots
2008            I=I, c[i]-sym[i];
2009          }
2010        }
2011        J= I, x@-C[ #[j]];
2012        // Notice that elim(...) is from the library "elim.lib",
2013        // it is loaded as a result of loading "general.lib"
2014        J=simplify(elim(J, E), 1);
2015        // get the expression of the next Chern class
2016        // in terms of the Chern classes of the initial vector bundle
2017        rez=rez+list( -subst(  J[1], x@, 0)  );
2018      }
2019      else // get out from the loop
2020      {
2021        break;
2022      }
2023    }
2024  }
2025  // used because Singular seems not to be able to apply maps to empty lists (see below)
2026  if(size(rez)==0)
2027  {
2028    return(list(N, list()));
2029  }
2030  setring br@; // come back to the initial base ring
2031  // define the specialization homomorphism,
2032  // evaluate the formulas for the Chern classes on their given values
2033  execute( "map FF = r@,0,"+varstr(br@)+";" );
2034  list rez=FF( rez ); // bring the result back to the initial ring
2035  return( list( N, rez  ) ); //return the rank and the Chern classes of the exterior product
2036}
2037example
2038{
2039  "EXAMPLE:";echo =2;
2040  ring r=0, (c(1..5)), dp;
2041  list l=c(1..5);
2042  // the rank and the Chern classes of the second exterior power of a vector bundle of rank 3
2043  print( chWedge(2, 3, l) );
2044  // the rank and the first 3 Chern classes
2045  // of the fourth exterior power of a vector bundle of rank 5
2046  print( chWedge(4, 5, l, 1, 2, 3) );
2047}
2048//---------------------------------------------------------------------------------
2049
2050proc chWedge2L(int r, list c)
2051"USAGE:   chWedge2L(r, c );  r integer, c list of polynomials
2052RETURN:   list of polynomials
2053PURPOSE:  computes the Chern classes of the second exterior power of a vector bundle
2054EXAMPLE:  example chWedge2L; shows an example
2055NOTE:     Implementation of the formula of Lascoux, the Schur polynomials are computed
2056          using the second Jacobi-Trudi formula (in terms of the Chern classes)
2057"
2058{
2059  // insure that the entries of c are polynomials
2060  // in order to be able to apply maps
2061  int i;
2062  for(i=1;i<=size(c);i++)
2063  {
2064    c[i]=poly(c[i]);
2065  }
2066  if(r<0) // if the rank is negative
2067  {
2068    print("The rank of a vector bundle can non be negative");
2069    return(list()); // return the empty list in this case
2070  }
2071  if(r==0) // if we deal with the zero bundle
2072  {
2073    return( list( 0, list() ) ); // return the data corresponding to the zero bundle
2074  }
2075  //-------------------------------------------
2076  // from now on we are in the case r > 0
2077  //-------------------------------------------
2078  c=append_by_zeroes(r, c);
2079  c=c[1..r];
2080  def br@=basering; // remember the base ring
2081  // add  additional variables to the base ring
2082  list l10 = ringlist(basering)[2];
2083  l10[size(l10)+1] = "t@";
2084  for (int ii = 1; ii <= r; ii++)
2085  {
2086   l10[size(l10)+1] = "c@("+string(ii)+")";
2087  }
2088  ring r@ = create_ring(ring_list(basering)[1], l10, "dp", "no_minpoly");
2089  execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
2090  list c;
2091  for(i=1;i<=r;i++)
2092  {
2093    c[i]=c@(i)*t@^i;
2094  }
2095  poly f = chWedge2LP(r,c); // get the total Chern class using the formula of Lascoux
2096  matrix CF = coeffs(f, t@);
2097  int N=r*(r-1) div 2;
2098  list rez; // write its coefficients in front of the powers of t@ to a list
2099  for(i=1;i<=N;i++)
2100  {
2101    rez=rez+list(CF[i+1,1]);
2102  }
2103  setring br@; // come back to the initial base ring
2104  execute("map FF = r@,"+varstr(br@)+",0, c[1..r];"); // define the specialization homomorphism
2105  return( list(N, FF( rez )) ); // bring the result to the initial ring
2106}
2107example
2108{
2109  "EXAMPLE:";echo =2;
2110  ring r=0, (c(1..3)), dp;
2111  list l=c(1..3);
2112  // the Chern classes of the second exterior power of a vector bundle of rank 3
2113  print(chWedge2L(3, l));
2114}
2115//---------------------------------------------------------------------------------------
2116
2117proc chWedge2LP(int r, list c)
2118"USAGE:   chWedge2LP(r, c );  r integer, c list of polynomials
2119RETURN:   poly
2120PURPOSE:  computes the total Chern class of the second exterior power of a vector bundle
2121EXAMPLE:  example chWedge2LP; shows an example
2122NOTE:     Implementation of the formula of Lascoux, the Schur polynomials are computed
2123          using the second Jacobi-Trudi formula (in terms of the Chern classes)
2124"
2125{
2126  if(r<0) // if the rank is negative
2127  {
2128    print("The rank of a vector bundle can non be negative");
2129    return(1); // return 1 in this case
2130  }
2131  if(r==0) // if we deal with the zero bundle
2132  {
2133    return( 1 ); // return 1 in this case
2134  }
2135  //-------------------------------------------
2136  // from now on we are in the case r > 0
2137  //-------------------------------------------
2138  c=append_by_zeroes(r, c);
2139  c=c[1..r];
2140  list I; // the partition (0,1,...,r-1) will be stored here
2141  int i;
2142  for(i=0;i<=r-1;i++)
2143  {
2144    I=I+list(i);
2145  }
2146  list PU = partUnder(I); // compute the partitions under I
2147  int sz=size(PU); // get their number
2148  poly rez; // the result will be computed here
2149  list J;
2150  poly cf;
2151  // implement the Lascoux formula
2152  for(i=1;i<=sz;i++)
2153  {
2154    J=PU[i];
2155    cf = IJcoef(I,J)/bigint(2)^( r*(r-1) div 2-sum(J)  );
2156    rez = rez + cf * SchurCh(J, c );
2157  }
2158  return(rez);
2159}
2160example
2161{
2162  "EXAMPLE:";echo =2;
2163  ring r=0, (c(1..3)), ws(1,2,3);
2164  list l=c(1..3);
2165  // the total Chern class of the second exterior power of a vector bundle of rank 3
2166  print(chWedge2LP(3, l));
2167}
2168//---------------------------------------------------------------------------------------
2169
2170proc todd(list c, list #)
2171"USAGE:   todd(l [, n] );  l a list of polynomials, n integer
2172RETURN:   list of polynomials
2173PURPOSE:  computes [the first n] terms of the Todd class
2174EXAMPLE:  example todd; shows an example
2175NOTE:     returns an empty list if l is empty
2176"
2177{
2178  int i, j, k;
2179  // insure that the entries of c are polynomials
2180  // in order to be able to apply maps
2181  for(i=1;i<=size(c); i++)
2182  {
2183    c[i]=poly(c[i]);
2184  }
2185  int n;
2186  # = integer_list(#)[1]; // take into account only the first integer entries that are positive
2187  if( size(#) == 0 ) // if there are no  optional parameters
2188  {
2189    n = size(c);
2190  }
2191  else
2192  {
2193    // set n to be 0, if the parameter is non-positive,
2194    // set n to the value of the parameter otherwise
2195    n = max( #[1], 0 );
2196    c = append_by_zeroes(n, c); // append c by zeroes if the length of c  is smaller than n
2197    if(n!=0) // throw away the redundant data if n is positive and smaller than the length of c
2198    {
2199      c = c[1..n];
2200    }
2201  }
2202  if(n==0) // return the empty list
2203  {
2204    return(list());
2205  }
2206  else // otherwise proceed as follows
2207  {
2208    def br@=basering; // remember the base ring
2209    // add  additional variables to the base ring
2210    list l11 = ringlist(basering)[2];
2211    l11[size(l11)+1] = "a@";
2212    for (int ii = 1; ii <= n; ii++)
2213    {
2214     l11[size(l11)+1] = "c@("+string(ii)+")";
2215    }
2216    ring r@ = create_ring(ring_list(basering)[1], l11, "dp", "no_minpoly");
2217    execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
2218    list c=F(c); // embed c into the bigger ring
2219    list prev;
2220    list next;
2221    next=tdTerms(n, c@(1)); // the Todd class terms of a line budle
2222    list step = tdTerms(n, a@);
2223    poly f;
2224    list hC=c@(1)-a@; // "old" first Chern class
2225    for(k=2;k<=n;k++) // do n-1 iterations
2226    {
2227      prev=next;
2228      next=list();
2229      hC=hC+list( c@(k)-a@*hC[k-1] ); // "old" k-th Chern class
2230      for(i=0;i<k;i++) // these terms have already been computed in the previous iterations
2231      {
2232        next = next + list(prev[i+1]);
2233      }
2234      for(i=k;i<=n;i++) // new values in terms of "old" Chern classes and the Chern root a
2235      {
2236        f=0;
2237        for(j=0; j<=i; j++)
2238        {
2239          f=f + step[j+1]*prev[i-j+1];
2240        }
2241        // substitute the old values of Chern classes
2242        // by their expressions in the new ones and the Chern root a
2243        for(j=1;j<k;j++)
2244        {
2245          f=subst(f, c@(j), hC[j] );
2246        }
2247        f=reduce(f, std(hC[k]) ); // eliminate the Chern root
2248        next = next + list(f);
2249      }
2250    }
2251    next = delete(next, 1); // throw away the zeroth term which is always equal to 1
2252    setring br@; // come back to the initial base ring
2253    execute("map FF = r@,"+varstr(br@)+",0, c[1..n];"); // define the specialization homomorphism
2254    return( FF( next ) ); // bring the result to the initial ring
2255  }
2256}
2257example
2258{
2259  "EXAMPLE:";echo =2;
2260  // the terms of the Todd class up to degree 5
2261  // in terms of the Chern classes c(1), c(2), c(3), c(4), c(5)
2262  ring r=0, (c(1..5)), dp;
2263  list l=c(1..5);
2264  print( todd( l ) );
2265
2266  // in the same situation compute only first two terms
2267  print( todd(l, 2) );
2268
2269  // compute the first 5 terms corresponding to the Chern classes c(1), c(2)
2270  l=c(1..2);
2271  print( todd(l, 5) );
2272}
2273//------------------------------------------------------------------------------------------
2274
2275proc toddE(list c)
2276"USAGE:   toddE(l);  l a list of polynomials
2277RETURN:   polynomial
2278PURPOSE:  computes the highest relevant term of the Todd class
2279EXAMPLE:  example toddE; shows an example
2280NOTE:     returns an empty list if l is empty,
2281          very inefficient because the elimination is used, included for comparison with todd(c)
2282"
2283{
2284  int i;
2285  for(i=1;i<=size(c);i++)
2286  {
2287    c[i]=poly( c[i] );
2288  }
2289  int n=size(c);
2290  if(n==0) // return the empty list if c is empty
2291  {
2292    return(list());
2293  }
2294  else
2295  {
2296    def br@=basering; // remember the base ring
2297    // add additional variables a@(1..n), x@ to the base ring
2298    list l12 = "x@";
2299    l12 = l12+ ringlist(basering)[2];
2300    for (int ii = 1; ii <= n; ii++)
2301    {
2302     l12[size(l12)+1] = "a@("+string(ii)+")";
2303    }
2304    ring r@ = create_ring(ring_list(basering)[1], l12, "lp", "no_minpoly");
2305    execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings
2306    list c=F(c); // embed c into the bigger ring
2307    int j;
2308    int k;
2309    poly E = a@(1); // to be the product of the Chern roots that will be eliminated later
2310    list ss=tdTerms( n, a@(1) );
2311    list next; // to be the terms of the Todd class corresponding to the next Chern root
2312    for(i=2;i<=n;i++) // compute the terms of the Todd class in terms of the Chern roots
2313    {
2314      E=E*a@(i); // to compute the product of variables to be eliminated
2315      next=tdTerms( n, a@(i) );
2316      for(j=n;j>=1;j--)
2317      {
2318        for(k=0;k<j;k++)
2319        {
2320          ss[j+1]=ss[j+1]+ss[k+1]*next[j-k+1];
2321        }
2322      }
2323    }
2324    ideal I=x@ - ss[n+1]; // formula for the highest degree term of the Todd class
2325    list sym=symm(list(a@(1..n))); // expressions for the Chern classes in terms of the Chern roots
2326    for(i=1;i<=n;i++)
2327    {
2328      I=I, c[i]-sym[i]; // add the relations
2329    }
2330    I=simplify(elim(I, E), 1); // eliminate the Chern roots
2331    poly rez=-subst(I[1],x@, 0); // get the required formula
2332    setring br@; // come back to the initial base ring
2333    // define the specialization homomorphism (all added variables are set to zero)
2334    execute( "map FF = r@,0, "+varstr(br@)+";" );
2335    poly rez=FF( rez ); // bring the result back to the initial base ring
2336    return(rez);
2337  }
2338}
2339example
2340{
2341  "EXAMPLE:";echo =2;
2342  // first  3 terms of the Todd class in terms of the Chern classes c(1), c(2), c(3)
2343  ring r=0, (c(1..3)), dp;
2344  list l;
2345  //first term
2346  l=c(1);
2347  print( toddE( l ) );
2348  // second term
2349  l=c(1..2);
2350  print( toddE( l ) );
2351  // third term
2352  l=c(1..3);
2353  print( toddE( l ) );
2354}
2355//---------------------------------------------------------------------------------
2356
2357proc  Bern(int n)
2358"USAGE:   Bern(n);  n non-negative integer
2359RETURN:   list of numbers
2360PURPOSE:  computes the list of (second) Bernoulli numbers from B(0) to B(n)
2361EXAMPLE:  example Bern; shows an example
2362NOTE:     needs a base ring to be defined, returns an empty list if n is negative,
2363          uses the Akiyama-Tanigawa algorithm
2364"
2365{
2366  // the Akiyama-Tanigawa algorithm
2367  //could be replaced by a more efficient one
2368  list rez, steprez;
2369  int i, j;
2370  if(n<0) // if n is negative, return the empty list
2371  {
2372    return(list());
2373  }
2374  for(i=0;i<=n;i++)
2375  {
2376    steprez=steprez+list( 1/number(i+1) );
2377    for(j=i;j>=1;j--)
2378    {
2379      steprez[j]=j*(steprez[j]-steprez[j+1]);
2380    }
2381    rez=rez+list(steprez[1]);
2382  }
2383  return(rez);
2384}
2385example
2386{
2387  "EXAMPLE:";echo =2;
2388  // first 10 Bernoulli numbers: B(0), ..., B(9)
2389  ring r=0,(t), dp;
2390  print( Bern(9) );
2391}
2392//---------------------------------------------------------------------------------
2393
2394proc tdCf(int n)
2395"USAGE:   tdCf(n);  n integer
2396RETURN:   list of rational numbers
2397PURPOSE:  computes up to degree n the coefficients of the Todd class of a line bundle
2398EXAMPLE:  example tdCf; shows an example
2399NOTE:
2400"
2401{
2402  list rez=Bern(n); // notice that Bern(n) is able to take care of negative n
2403  int i;
2404  for(i=1;i<=n+1;i++)
2405  {
2406  rez[i]=rez[i]/factorial(i-1);
2407  }
2408  return(rez);
2409}
2410example
2411{
2412  "EXAMPLE:";echo =2;
2413  // first 5 coefficients
2414  ring r=0,(t), dp;
2415  print( tdCf(4) );
2416}
2417//---------------------------------------------------------------------------------
2418
2419proc tdTerms(int n, poly f)
2420"USAGE:   tdTerms(n, f);  n integer, f polynomial
2421RETURN:   list of polynomials
2422PURPOSE:  computes the terms of the Todd class of the line bundle with the Chern root f
2423EXAMPLE:  example tdTerms; shows an example
2424NOTE:
2425"
2426{
2427  list rez=Bern(n); // notice that Bern(n) takes care of negative n
2428  int i;
2429  for(i=1;i<=n+1;i++)
2430  {
2431  rez[i]=( rez[i]/factorial(i-1) )* f^(i-1);
2432  }
2433  return(rez);
2434}
2435example
2436{
2437  "EXAMPLE:";echo =2;
2438  ring r=0, (t), ls;;
2439  // the terms of the Todd class of a line bundle with Chern root t up to degree 4
2440  print( tdTerms(4, t) );
2441}
2442//---------------------------------------------------------------------------------
2443
2444proc tdFactor(int n, poly t)
2445"USAGE:   tdFactor(n, a);  n integer, a polynomial
2446RETURN:   polynomial
2447PURPOSE:  computes up to degree n the Todd class
2448          of the line bundle corresponding to the Chern root t
2449EXAMPLE:  example tdFactor; shows an example
2450NOTE:     returns 0 if n is negative
2451"
2452{
2453  int i;
2454  poly rez=0;
2455  list l=Bern(n); // get the coefficients
2456  for(i=0; i<=n; i++) // form the polynomial
2457  {
2458    rez=rez+(l[i+1]/factorial(i))*t^i;
2459  }
2460  return(rez);
2461}
2462example
2463{
2464  "EXAMPLE:";echo =2;
2465  // the Todd class up do degree 4
2466  ring r=0,(t), ls;
2467  print( tdFactor(4, t) );
2468}
2469//---------------------------------------------------------------------------------
2470
2471proc cProj(int n)
2472"USAGE:   cProj(n);  n  integer
2473RETURN:   list of integers
2474PURPOSE:  computes the terms of positive degree of the total Chern class
2475          of the tangent bundle on the complex projective space
2476EXAMPLE:  example cProj; shows an example
2477NOTE:
2478"
2479{
2480  if(n<0)
2481  {
2482    print("The dimension of the projective space must be non-negative!");
2483    return(list()); // return the empty list in this case
2484  }
2485  else
2486  {
2487    list rez;
2488    int i;
2489    for(i=1;i<=n;i++)
2490    {
2491      rez=rez+list( binomial(n+1, i) );
2492    }
2493    return(rez);
2494  }
2495}
2496example
2497{
2498  "EXAMPLE:";echo =2;
2499  ring r=0, (t), dp;
2500  // the coefficients of the total Chern class of the complex projective line
2501  print( cProj(1) );
2502
2503  // the coefficients of the total Chern class of the complex projective plane
2504  print( cProj(2) );
2505
2506  // the coefficients of the total Chern class of the complex projective space
2507  // of dimension three
2508  print( cProj(3) );
2509}
2510//------------------------------------------------------------------------------------------
2511
2512proc chProj(int n)
2513"USAGE:   chProj(n);  n  integer
2514RETURN:   list of (rational) numbers
2515PURPOSE:  computes the terms of the Chern character of the tangent bundle
2516          on the complex projective space
2517EXAMPLE:  example chProj; shows an example
2518NOTE:
2519"
2520{
2521  if(n<0)
2522  {
2523    print("The dimension of the projective space must be non-negative!");
2524    return( list() ); // return the empty list in this case
2525  }
2526  else
2527  {
2528    list rez=list(number(n));
2529    int i;
2530    for(i=1;i<=n;i++)
2531    {
2532      rez=rez+list( (n+1)/factorial(i) );
2533    }
2534    return(rez);
2535  }
2536}
2537example
2538{
2539  "EXAMPLE:";echo =2;
2540  ring r=0, (t), dp;
2541  // the coefficients of the Chern character of the complex projective line
2542  print( chProj(1) );
2543
2544  // the coefficients of the Chern character of the complex projective plane
2545  print( chProj(2) );
2546
2547  // the coefficients of the Chern character of the complex 3-dimensional projective space
2548  print( chProj(3) );
2549}
2550//------------------------------------------------------------------------------------------
2551
2552proc tdProj(int n)
2553"USAGE:   tdProj(n);  n  integer
2554RETURN:   list of (rational) numbers
2555PURPOSE:  computes the terms of the Todd class
2556          of the (tangent bundle of the) complex projective space
2557EXAMPLE:  example tdProj; shows an example
2558NOTE:
2559"
2560{
2561  if(n<0)
2562  {
2563    print("The dimension of the projective space must be non-negative!");
2564    return( list() ); // return the empty list in this case
2565  }
2566  else
2567  {
2568    def br@=basering; // remember the base ring
2569    ring r@= 0, t@, lp; // ring with one variable t@
2570    ideal T=std( t@^(n+1) );
2571    poly f= tdFactor(n, t@);
2572    f=reduce( f^(n+1), T);
2573    matrix C = coeffs(f, t@);
2574    list rez;
2575    int i;
2576    for(i=0;i<=n;i++)
2577    {
2578     rez=rez+list(C[i+1, 1]);
2579    }
2580    setring br@; // come back to the initial base ring
2581    map FF= r@, 0 ; // define the specialization homomorphism t@=0
2582    return(FF(rez)); // bring the result to the base ring
2583  }
2584}
2585example
2586{
2587  "EXAMPLE:";echo =2;
2588  ring r=0, (t), dp;
2589
2590  // the coefficients of the Todd class of the complex projective line
2591  print( tdProj(1) );
2592
2593  // the coefficients of the Todd class of the complex projective line
2594  print( tdProj(2) );
2595
2596  // the coefficients of the Todd class of the complex projective line
2597  print( tdProj(3) );
2598}
2599//------------------------------------------------------------------------------------------
2600
2601proc eulerChProj(int n, def r, list c)
2602"USAGE:   eulerChProj(n, r, c);  n  integer, r polynomial (or integer), c list of polynomials
2603RETURN:   polynomial
2604PURPOSE:  computes the Euler characteristic of a vector bundle on P_n
2605          in terms of its rank and Chern classes
2606EXAMPLE:  example eulerChProj; shows an example
2607NOTE:
2608"
2609{
2610  if(n<0)
2611  {
2612    print("The dimension of the projective space must be non-negative!");
2613    return(0); // return zero in this case
2614  }
2615  else
2616  {
2617    if(n==0)
2618    {
2619      return(r);
2620    }
2621    // now n is at least 1
2622    c=append_by_zeroes(n, c); // append c by zeroes if its size is smaller than n
2623    c=c[1..n]; // throw away the redundant data
2624    // now the size of c is n
2625    list td = tdProj(n); // terms of the Todd class of P_n
2626    list ch = list(r) + chAll(c); // terms of the Chern character of the vector bundle
2627    return( rHRR(n, ch, td) );
2628  }
2629}
2630example
2631{
2632  "EXAMPLE:";echo =2;
2633  ring h=0, (r, c(1..3)),  ws(0,1,2,3);
2634  list l=c(1..3);
2635  // the Euler characteristic of a vector bundle on the projective line
2636  print( eulerChProj(1, r, l) );
2637
2638  // the Euler characteristic of a vector bundle on the projective plane
2639  print( eulerChProj(2, r, l) );
2640
2641  // the Euler characteristic of a vector bundle on P_3
2642  print( eulerChProj(3, r, l) );
2643
2644  // assume now that we have a bundle framed at a subplane of P_3
2645  // this implies c(1)=c(2)=0
2646  l= 0, 0, c(3);
2647
2648  // the Euler characteristic is
2649  print( eulerChProj(3, r, l) );
2650  // which implies that c(3) must be even in this case
2651}
2652//-------------------------------------------------------
2653
2654proc chNumbersProj(int n)
2655"USAGE:   chNumbersProj(n);  n  integer
2656RETURN:   list of integers
2657PURPOSE:  computes the Chern numbers of the projective space P_n
2658EXAMPLE:  example chNumbersProj; shows an example
2659NOTE:
2660"
2661{
2662  return( chNumbers( n, cProj(n) ) );
2663}
2664example
2665{
2666  "EXAMPLE:";echo =2;
2667  ring h=0, (t), dp;
2668  // The Chern numbers of the projective plane P_2:
2669  print( chNumbersProj(2) );
2670
2671  // The Chern numbers of P_3:
2672  print( chNumbersProj(3) );
2673}
2674//-------------------------------------------------------
2675
2676proc classpoly(list l, poly t)
2677"USAGE:   classpoly(l, t);   l list of polynomials, t polynomial
2678RETURN:   polynomial
2679PURPOSE:  computes the polynomial in t with coefficients being the entries of l
2680EXAMPLE:  example classpoly; shows an example
2681NOTE:
2682"
2683{
2684  int n=size(l);
2685  poly pow=1; // powers of t will be compured here
2686  poly rez=0; // result will be computed here
2687  int i;
2688  for(i=1; i<=n; i++)
2689  {
2690    pow=pow*t; // compute the required power of t
2691    // add the i-th entry of l multiplied by the corresponding power of t to the result
2692    rez=rez + l[i]*pow;
2693  }
2694  return( rez );
2695}
2696example
2697{
2698  "EXAMPLE:";echo=2;
2699  ring r=0, (c(1..5), t), ds;
2700  list l=c(1..5);
2701  // get the polynomial c(1)*t + c(2)*t^2 + ... + c(5)*t^5
2702  print( classpoly(l, t) );
2703}
2704//----------------------------------------------------------------------------------------
2705
2706proc chernPoly(list c, poly t)
2707"USAGE:   chernPoly(c, t);   c list of polynomials, t polynomial
2708RETURN:   polynomial
2709PURPOSE:  computes the Chern polynomial in t
2710EXAMPLE:  example chernPoly; shows an example
2711NOTE: does the same as toddPoly(...)
2712"
2713{
2714  return( 1+classpoly(c, t) );
2715}
2716example
2717{
2718  "EXAMPLE:";echo=2;
2719  ring r=0, (c(1..5), t), ds;
2720  list l=c(1..5);
2721  // get the Chern polynomial 1 + c(1)*t + c(2)*t^2 + ... + c(5)*t^5
2722  print( chernPoly(l, t) );
2723}
2724//----------------------------------------------------------------------------------------
2725
2726proc chernCharPoly(poly r, list ch, poly t)
2727"USAGE:   chernCharPoly(r, ch, t);   r polynomial, ch list of polynomials, t polynomial
2728RETURN:   polynomial
2729PURPOSE:  computes the polynomial in t corresponding to the Chern character
2730EXAMPLE:  example chernpoly; shows an example
2731NOTE:
2732"
2733{
2734  return( r+classpoly(ch, t) );
2735}
2736example
2737{
2738  "EXAMPLE:";echo=2;
2739  ring h=0, (r, ch(1..5), t), ds;
2740  list l=ch(1..5);
2741  // get the polynomial r + ch(1)*t + ch(2)*t^2 + ... + ch(5)*t^5
2742  print( chernCharPoly(r, l, t) );
2743}
2744//----------------------------------------------------------------------------------------
2745
2746proc toddPoly(list td, poly t)
2747"USAGE:   toddPoly(td, t);   td list of polynomials, t polynomial
2748RETURN:   polynomial
2749PURPOSE:  computes the polynomial in t corresponding to the Todd class
2750EXAMPLE:  example toddPoly; shows an example
2751NOTE:     does the same as chernPoly(...)
2752"
2753{
2754  return( 1+classpoly(td, t) );
2755}
2756example
2757{
2758  "EXAMPLE:"; echo=2;
2759  ring r=0, (td(1..5), c(1..5), t), ds;
2760  list l=td(1..5);
2761  // get the polynomial 1 + td(1)*t + td(2)*t^2 + ... + td(5)*t^5
2762  print( toddPoly(l, t) );
2763}
2764//---------------------------------------------------------------------------------------
2765
2766proc rHRR(int N, list ch, list td)
2767"USAGE:   rHRR( N, ch, td);  N integer, ch, td  lists of polynomials
2768RETURN:   polynomial
2769PURPOSE:  computes the the main ingredient of the right-hand side
2770          of the Hirzebruch-Riemann-Roch formula
2771EXAMPLE:  example rHRR; shows an example
2772NOTE:     in order to get the right-hand side of the HRR formula
2773          one needs to be able to compute the degree of the output of this procedure
2774"
2775{
2776  poly rez; // to be the result
2777  int i;
2778  int nch=size(ch); // length of ch
2779  int ntd=size(td); // length of td
2780  for(i=1; i<=N+1; i++) // compute the highest degree term of ch.td
2781  {
2782    if( (i<=nch) && (N-i+2 <= ntd) )
2783    {
2784      rez = rez + ch[i]*td[N-i+2];
2785    }
2786  }
2787  return(rez);
2788}
2789example
2790{
2791  "EXAMPLE:"; echo=2;
2792  ring r=0, (td(0..3), ch(0..3)), dp;
2793  // Let ch(0), ch(1), ch(2), ch(3) be the terms of the Chern character
2794  // of a vector bundle E on a 3-fold X.
2795  list c = ch(0..3);
2796  // Let td(0), td(1), td(2), td(3) be the terms of the Todd class of X.
2797  list t = td(0..3);
2798  // Then the highest term of the product ch(E).td(X) is:
2799  print( rHRR(3, c, t) );
2800}
2801//---------------------------------------------------------------------------------------
2802
2803proc SchurS(list I, list S)
2804"USAGE:   SchurS(I, S);  I list of integers representing a partition, S list of polynomials
2805RETURN:   poly
2806PURPOSE:  computes the Schur polynomial in the Segre classes S (of the dual vector bundle),
2807          i.e., in the  complete homogeneous symmetric polynomials, with respect to the partition I
2808EXAMPLE:  example SchurS; shows an example
2809NOTE:     if S are the Segre classes of the tautological bundle on a grassmanian,
2810          this gives the cohomology class of a Schubert cycle
2811"
2812{
2813  int m=size(I); // size of I
2814  S=list(1)+S; // add the zeroth Segre class
2815  int szS=size(S); // size of S
2816  int h,k;
2817  int in; // variable for the index of the required Segre class
2818  // construct the required m x m matrix from the first determinantal (Jacobi-Trudi) formula
2819  matrix M[m][m];
2820  for(h=1;h<=m;h++)
2821  {
2822    for(k=1;k<=m;k++)
2823    {
2824      in=I[k]+k-h; // compute the index
2825      if(in<0) // if it is negative, assume the corresponding Segre class to be zero
2826      {
2827        M[h,k]=0;
2828      }
2829      else
2830      {
2831        if(in>=szS) // if it is bigger than the number of the highest available Segre class in S
2832        {
2833          M[h, k]=0; // assume the corresponding Segre class is zero
2834        }
2835        else // otherwise
2836        {
2837          M[h, k]= S[in+1]; // use a value from S for the corresponding Segre class
2838        }
2839      }
2840    }
2841  }
2842  return(det(M)); // return the determinant of the computed matrix
2843}
2844example
2845{
2846  "EXAMPLE:"; echo=2;
2847  // The Schur polynomial corresponding to the partition 1,2,4
2848  // and the Segre classes 1, s(1), s(2),..., s(6)
2849  ring r=0,(s(1..6)), dp;
2850  list I=1,2,4;
2851  list S=s(1..6);
2852  print( SchurS(I, S) );
2853  // compare this with the Schur polynomial computed using Chern classes
2854  list C=chDual(chern(S));
2855  print( SchurCh(I, C) );
2856}
2857//---------------------------------------------------------------------------------------
2858
2859proc SchurCh(list I, list C)
2860"USAGE:   SchurCh(I, C);  I list of integers representing a partition, C list of polynomials
2861RETURN:   poly
2862PURPOSE:  computes the Schur polynomial in the Chern classes C,
2863          i.e., in the elementary symmetric polynomials, with respect to the partition I
2864EXAMPLE:  example SchurCh; shows an example
2865NOTE:     if C are the Chern classes of the tautological bundle on a grassmanian,
2866          this gives the cohomology class of a Schubert cycle
2867"
2868{
2869  I=dualPart(I); // dual partition to I
2870  int m=size(I); // size of I
2871  C=list(1)+C; // add the zeroth Chern class
2872  int szC=size(C); // size of C
2873  int h,k;
2874  int in; // variable for the index of the required Chern class
2875  // construct the required m x m matrix from the second determinantal (Jacobi-Trudi) formula
2876  matrix M[m][m];
2877  for(h=1;h<=m;h++)
2878  {
2879    for(k=1;k<=m;k++)
2880    {
2881      in=I[k]+k-h; // compute the index
2882      if(in<0) // if it is negative, assume the corresponding Chern class to be zero
2883      {
2884        M[h,k]=0;
2885      }
2886      else
2887      {
2888        if(in>=szC) // if it is bigger than the number of the highest available Chern class in C
2889        {
2890          M[h, k]=0; // assume the corresponding Chern class is zero
2891        }
2892        else // otherwise
2893        {
2894          M[h, k]= C[in+1]; // use a value from C for the corresponding Chern class
2895        }
2896      }
2897    }
2898  }
2899  return(det(M)); // return the determinant of the computed matrix
2900}
2901example
2902{
2903  "EXAMPLE:"; echo=2;
2904  // The Schur polynomial corresponding to the partition 1,2,4
2905  // and the Chern classes c(1), c(2), c(3)
2906  ring r=0,(c(1..3)), dp;
2907  list I=1,2,4;
2908  list C=c(1..3);
2909  print( SchurCh(I, C) );
2910  // Compare this with the Schur polynomial computed using Segre classes
2911  list S=segre( chDual( list(c(1..3)) ), 6 );
2912  print(SchurS(I,S));
2913}
2914//---------------------------------------------------------------------------------------
2915
2916proc part(int m, int n)
2917"USAGE:   part( m, n );  m positive integer, n non-negative integer
2918RETURN:   list of lists
2919PURPOSE:  computes all partitions of integers not exceeding n into m non-negative summands
2920EXAMPLE:  example part; shows an example
2921NOTE:     if n is negative or m is non-positive, the list with one empty entry is returned
2922"
2923{
2924  if( n<0 ) // if n is negative
2925  {
2926    return(list(list())); // return the list with one empty entry
2927  }
2928  if(n==0) // if n equals 0, there is only one partition of 0 into m non-negative summands
2929  {
2930    return(list(listSame(0,m))); // return the list with one entry consistion of m zeroes
2931  }
2932  // otherwise proceed recursively
2933  list rez=part(m, n-1); // get all partitions for n-1
2934  int i;
2935  for(i=1;i<=m;i++) // for every i between 1 and m, add the partitions with exactly
2936  {
2937    rez=rez + appendToAll( part(m-i, n-1), listSame(n, i) ); // i summands equal to n
2938  }
2939  return(rez); // return the result
2940}
2941example
2942{
2943  "EXAMPLE:"; echo=2;
2944  // partitions into 3 summands of numbers not exceeding 1
2945  print( part(3, 1) );
2946}
2947//---------------------------------------------------------------------------------------
2948
2949proc dualPart(list I, list #)
2950"USAGE:   dualPart( I [,N] );  I list of integers, N integer
2951RETURN:   list of integers
2952PURPOSE:  computes the partition dual (conjugate) to I
2953EXAMPLE:  example dualPart; shows an example
2954NOTE:     the result is extended by zeroes to length N if an optional integer
2955          parameter N is given and the length of the computed  dual partition
2956          is smaller than N
2957"
2958{
2959  int m= size(I); // size of I
2960  if(m==0) // if I is the empty list
2961  {
2962    print("You are trying to compute the dual of the empty partition!");
2963    print("The partition with one zero is returned.");
2964    return(list(0));
2965  }
2966  // compute the dual partition
2967  list J; // the result will be computed here
2968  int i;
2969  int j=I[1];
2970  int k;
2971  for(k=1;k<=j;k++)
2972  {
2973    J=list(m)+J;
2974  }
2975  for(i=2;i<=m;i++)
2976  {
2977    j=I[i]-I[i-1];
2978    for(k=1;k<=j;k++)
2979    {
2980      J=list(m-i+1)+J;
2981    }
2982  }
2983  if(size(J)==0) // if the dual partition J is empty (if I consists of zeroes)
2984  {
2985    J = list(0); // add zero to the result
2986  }
2987  if(size(#)>0) // if there is an optional parameter N
2988  {
2989    if( is_integer( #[1] ) ) // if the parameter is an integer,
2990    {
2991      if( size(J) < #[1] ) // if N  is bigger than the length of J,
2992      {
2993        J=listSame(0, #[1]-size(J))+J; // extend J by zeroes to length N
2994      }
2995    }
2996  }
2997  return(J); // return the result
2998}
2999example
3000{
3001  "EXAMPLE:"; echo =2;
3002  // dual partition to (1, 3, 4):
3003  list I = 1, 3, 4;
3004  print( dualPart(I) );
3005}
3006//---------------------------------------------------------------------------------------
3007
3008proc PartC(list I, int m)
3009"USAGE:   PartC( I, m);  I list of integers, m integer
3010RETURN:   list of integers
3011PURPOSE:  computes the complement of a partition with respect to m
3012EXAMPLE:  example PartC; shows an example
3013NOTE:     returns the zero partition if the maximal element of the partition is smaller than m
3014"
3015{
3016  int n=size(I); // size of I
3017  if( m<I[n] ) // if m is smaller than the last term of I,
3018  {
3019    // give a warning
3020    print("You are trying to compute a complement of a partition with respect");
3021    print("to a number that is smaller than the maximal summand of the partition!");
3022    print("The zero partition is returned.");
3023    return(list(0)); // and return the zero partition
3024  }
3025  list J; // the result will be computed here
3026  int i;
3027  for(i=n;i>=1;i--) // invert the order of numbers
3028  {
3029    J=J+list(m-I[i]); // and substitute them by their complemenst to m
3030  }
3031  return(J); // return the result
3032}
3033example
3034{
3035  "EXAMPLE:"; echo =2;
3036  // Complement of the partition (1, 3, 4) with respect to 5
3037  list I = 1, 3, 4;
3038  print( PartC(I, 5) );
3039}
3040//---------------------------------------------------------------------------------------
3041
3042proc partOver(int n, list J)
3043"USAGE:   partOver( n, J);  n integer, J list of integers (partition)
3044RETURN:   list of lists
3045PURPOSE:  computes the partitions over a given one  with summands not exceeding n
3046EXAMPLE:  example partOver; shows an example
3047NOTE:
3048"
3049{
3050  int m=size(J); // size of J
3051  if( m==0 ) // if J is an empty list
3052  {
3053    // give a warning
3054    print("You are trying to compute partitions over an empty partition!");
3055    return( list() ); // and return the empty list
3056  }
3057  if( J[m] > n ) // if the biggest summand of the partition is bigger than n
3058  {
3059    return( list( ) ); // return the empty list
3060  }
3061  if( J[m] == 0 ) // if J consists of zeroes
3062  {
3063    return( part(m,n) ); // return all partitions of n into m summands
3064  }
3065  // now J is non-empty, contains con-zero summands, has partitions over it
3066  list rez1; // the result will be computed here
3067  int i,j;
3068  if(m==1) // if J has only one element
3069  {
3070    for(j=J[1]; j<=n; j++) // run through the integers from J[1] to n
3071    {
3072      rez1=rez1 + list(j); // add the corresponding one element lists to the result
3073    }
3074    return(rez1); // return the result
3075  }
3076  // now J has at least two elements
3077  // get the partitions over the partition without the last summand
3078  list rez = partOver(n, delete(J, m));
3079  int sz=size(rez); // number of such partitions
3080  list P;
3081  int last;
3082  for(i=1; i<=sz; i++) // run trough all such partitions
3083  {
3084    P=rez[i]; // for each partition P of this type
3085    last = max( P[size(P)], J[m] );
3086    for(j = last;j<= n;j++) // run through the integers exceeding the last summands of P and J
3087    {
3088      // append them to P at the end and add the resulting partition to the result
3089      rez1=rez1 + list(P+list(j));
3090    }
3091  }
3092  return(rez1); // return the result
3093}
3094example
3095{
3096  "EXAMPLE:"; echo =2;
3097  // Partitions over the partition (3, 3, 4) with summands not exceeding 4
3098  list I = 3, 3, 4;
3099  print( partOver(4, I) );
3100}
3101//---------------------------------------------------------------------------------------
3102
3103proc partUnder(list J)
3104"USAGE:   partUnder(J);  J list of integers (partition)
3105RETURN:   list of lists
3106PURPOSE:  computes the partitions under a given one
3107EXAMPLE:  example partUnder; shows an example
3108NOTE:
3109"
3110{
3111  int m=size(J); // size of J
3112  if(m==0) // if J is empty
3113  {
3114    return(list()); // return an empty list
3115  }
3116  list rez1; // the result will be computed here
3117  int i;
3118  if(m==1) // if J contains only one element
3119  {
3120    for(i=0; i<=J[1]; i++)
3121    {
3122      rez1=rez1+list(list(i));
3123    }
3124  }
3125  // now J contains at least two elements
3126  list rez;
3127  int Jlast=J[m]; // last element of J
3128  rez = partUnder(delete(J, m)); // partitions under J without the last element
3129  int j;
3130  int sz=size(rez); // their number
3131  list P;
3132  int last;
3133  for(i=1; i<=sz; i++) // for every such partition
3134  {
3135    P = rez[i];
3136    last = P[size(P)];
3137    for(j = last;j<=Jlast ;j++) // for every number between its last entry and the last entry of J
3138    {
3139      // append that number to the end of the partition
3140      // and append the resulting partition to the final result
3141      rez1 = rez1 + list(P+list(j));
3142    }
3143  }
3144  return(rez1);
3145}
3146example
3147{
3148  "EXAMPLE:"; echo =2;
3149  // Partitions under the partition (0, 1, 1)
3150  list I = 0, 1, 1;
3151  print( partUnder(I) );
3152}
3153//-------------------------------------------------------------------------------------------
3154
3155proc SegreA(ideal I)
3156"USAGE:   SegreA(I);  I an ideal
3157RETURN:   list of integers
3158PURPOSE:  computes the Segre classes of the subscheme defined by I
3159EXAMPLE:  example SegreA; shows an example
3160NOTE:
3161"
3162{
3163  if( !homog(I) ) // if the ideal is not homogeneous
3164  {
3165    print("You are trying to compute the Segre class of a non-homogeneous ideal!");
3166    print("The ideal must be homogeneous, an empty list is returned.");
3167    return( list() );
3168  }
3169  // modify the generators of the ideal so that all of them are of the same degree
3170  I=equal_deg(I);
3171  int degGen=deg(I[1]); // this degree d is stored in this variable
3172  int i;
3173  list rez; // define the variable for the result
3174  int n=nvars(basering)-1; // the dimension of the projective space
3175  if(degGen==-1) // if the ideal is zero
3176  {
3177    for(i=0;i<=n;i++)
3178    {
3179      rez=rez+ list( int((-1)^i*binomial(n+i, i)) );
3180    }
3181    return(rez);
3182  }
3183  int sz=ncols(I); // the number of new generators is stored here
3184  def br@=basering; // remember the base ring
3185  // add additional variables t@(1), ... , t@(sz) and u@ to the base ring
3186  list l13 = ringlist(basering)[2];
3187  for (int ii = 1; ii <= sz; ii++)
3188  {
3189   l13[size(l13)+1] = "t@("+string(ii)+")";
3190  }
3191  l13[size(l13)+1] = "u@";
3192  ring r@ = create_ring(ring_list(basering)[1], l13, "dp", "no_minpoly");
3193  ideal I=fetch(br@,I); // the ideal generated by I in the new ring
3194  ideal J(0..n); // define n+1 ideals J(0), ... , J(n)
3195  // compute the ideal of the Rees algebra of the ideal I:
3196  for(i=1; i<=sz; i++) // consider the ideal generated by t@(i)-u@*I[i]
3197  {
3198    J(0)=J(0) + ideal( t@(i)-u@*I[i] );
3199  }
3200  J(0)=eliminate(J(0), u@); // and eliminate the variable u@
3201  ideal T=t@(1..sz); // define the ideal generated by the additional variables t@(1), ... , t@(sz)
3202  for(i=1;i<=n;i++)// for all i=1, ... n define J(j) as in 3.6 of the Aluffi's paper
3203  {
3204    // add a random general linear form in variables t@(1), ... , t@(n) to J(i-1)
3205    J(i)=sat( random_hypersurf(J(i-1), T)   , T)[1]; // and saturate with respect to T
3206  }
3207  poly prd=product(T); // compute the product of t@(i)
3208  poly cl;
3209  poly mlt;
3210  for(i=0;i<=n;i++)
3211  {
3212    // eliminate all t@(i) from J(i)
3213    // compute the degree of the scheme defined by this ideal
3214    // and use it to compute the class corresponding to c(O(d))^n * G\otimes O(d)
3215    cl=cl+mult(std(eliminate(J(i), prd)))*u@^i*(1+degGen*u@)^(n-i);
3216    // the (n+1)-st power of the inverse of the Chern class of O(d)
3217    mlt=mlt+binomial(n+i, i)*(-degGen*u@)^i;
3218  }
3219  poly resPoly;
3220  // compute the Segre class by the Aluffi's formula from Proposition 3.1 as polynomial in u@
3221  resPoly= NF( 1-cl*mlt, u@^(n+1));
3222  matrix cf=coeffs(resPoly, u@); // coefficients of the Segre class
3223  rez=list(); // empty the list
3224  for(i=0;i<=n;i++) // fill the list with the the Segre classes in positive degrees
3225  {
3226    if( i < nrows(cf) ) // if i is not bigger than the maximal degree of non-zero Segre classes
3227    {
3228      rez=rez+list(int(cf[i+1,1]));
3229    }
3230    else // otherwise fill the list with zeroes
3231    {
3232      rez=rez+list( int(0) );
3233    }
3234  }
3235  return(rez);
3236}
3237example
3238{
3239  "EXAMPLE:";echo =2;
3240  // Consider a 3-dimensional projective space
3241  ring r = 0, (x, y, z, w), dp;
3242  // Consider 3 non-coplanar lines trough one point and compute the Segre class
3243  ideal I=xy, xz, yz;
3244  I;
3245  SegreA(I);
3246  // Now consider 3 coplanar lines trough one point and its Segre class
3247  ideal J=w, x*y*(x+y);
3248  J;
3249  SegreA(J);
3250}
3251//-------------------------------------------------------------------------------------------
3252
3253proc FultonA(ideal I)
3254"USAGE:   FultonA(I);  I an ideal
3255RETURN:   list of integers
3256PURPOSE:  computes the Fulton classes of the subscheme defined by I
3257EXAMPLE:  example FultonA; shows an example
3258NOTE:
3259"
3260{
3261  if( !homog(I) ) // if the ideal is not homogeneous
3262  {
3263    print("You are trying to compute the Segre class of a non-homogeneous ideal!");
3264    print("The ideal must be homogeneous, an empty list is returned.");
3265    return( list() );
3266  }
3267  // modify the generators of the ideal so that all of them are of the same degree
3268  I=equal_deg(I);
3269  int degGen=deg(I[1]); // this degree d is stored in this variable
3270  int i;
3271  list rez; // define the variable for the result
3272  int n=nvars(basering)-1; // the dimension of the projective space
3273  if(degGen==-1) // if the ideal is zero
3274  {
3275    rez=rez+list(int(1));
3276    for(i=1;i<=n;i++)
3277    {
3278      rez=rez+ list( int(0) );
3279    }
3280    return(rez);
3281  }
3282  int sz=ncols(I); // the number of new generators is stored here
3283  def br@=basering; // remember the base ring
3284  // add additional variables t@(1), ... , t@(sz) and u@ to the base ring
3285  list l14 = ringlist(basering)[2];
3286  for (int ii = 1; ii <= sz; ii++)
3287  {
3288   l14[size(l14)+1] = "t@("+string(ii)+")";
3289  }
3290  l14[size(l14)+1] = "u@";
3291  ring r@ = create_ring(ring_list(basering)[1], l14, "dp", "no_minpoly");
3292  ideal I=fetch(br@,I); // the ideal generated by I in the new ring
3293  ideal J(0..n); // define n+1 ideals J(0), ... , J(n)
3294  // compute the ideal of the Rees algebra of the ideal I:
3295  for(i=1; i<=sz; i++) // consider the ideal generated by t@(i)-u@*I[i]
3296  {
3297    J(0)=J(0) + ideal( t@(i)-u@*I[i] );
3298  }
3299  J(0)=eliminate(J(0), u@); // and eliminate the variable u@
3300  ideal T=t@(1..sz); // define the ideal generated by the additional variables t@(1), ... , t@(sz)
3301  for(i=1;i<=n;i++)// for all i=1, ... n define J(j) as in 3.6 of the Aluffi's paper
3302  {
3303    // add a random general linear form in variables t@(1), ... , t@(n) to J(i-1)
3304    J(i)=sat(   random_hypersurf(J(i-1), T)  , T)[1]; // and saturate with respect to T
3305  }
3306  poly prd=product(T); // compute the product of t@(i)
3307  poly cl;
3308  poly mlt;
3309  for(i=0;i<=n;i++)
3310  {
3311    // eliminate all t@(i) from J(i)
3312    // compute the degree of the scheme defined by this ideal
3313    // the class corresponding to c(O(d))^n * G\otimes O(d)
3314    cl=cl+ mult(std( eliminate( J(i),  prd) ))*u@^i*(1+degGen*u@)^(n-i);
3315    // the (n+1)-st power of the inverse of the Chern class of O(d)
3316    mlt=mlt+binomial(n+i, i)*(-degGen*u@)^i;
3317  }
3318  poly resPoly;
3319  // compute the Fulton class using the Aluffi's formula for the Segre class and
3320  // multiplying it by the Chern class of the projective space (1+u@)^(n+1)
3321  resPoly= NF( (1+u@)^(n+1)*(1-cl*mlt), u@^(n+1) );
3322  matrix cf=coeffs(resPoly, u@); // coefficients of the Fulton class
3323  rez=list(); // empty the list
3324  for(i=0;i<=n;i++) // fill the list with the the Fulton classes in positive degrees
3325  {
3326    if( i < nrows(cf) ) // if i is not bigger than the maximal degree of non-zero Fulton classes
3327    {
3328      rez=rez+list(int(cf[i+1,1]));
3329    }
3330    else // otherwise fill the list with zeroes
3331    {
3332      rez=rez+list( int(0) );
3333    }
3334  }
3335  return(rez);
3336}
3337example
3338{
3339  "EXAMPLE:";echo =2;
3340  // Consider a 3-dimensional projective space
3341  ring r = 0, (x, y, z, w), dp;
3342  // Consider 3 non-coplanar lines trough one point and compute the Fulton class
3343  ideal I=xy, xz, yz;
3344  I;
3345  FultonA(I);
3346  // Now consider 3 coplanar lines trough one point and its Fulton class
3347  ideal J=w, x*y*(x+y);
3348  J;
3349  FultonA(J);
3350}
3351//-------------------------------------------------------------------------------------------
3352
3353proc CSMA(ideal I)
3354"USAGE:   CSMA(I);  I an ideal
3355RETURN:   list of integers
3356PURPOSE:  computes the Chern-Schwartz-MacPherson classes of the variety defined by I
3357EXAMPLE:  example CSMA; shows an example
3358NOTE:
3359"
3360{
3361  if( !homog(I) ) // if the ideal is not homogeneous
3362  {
3363    print("You are trying to compute the Chern-Schwartz-MacPherson class.");
3364    print("However the input ideal is not homogeneous!");
3365    print("The ideal must be homogeneous, an empty list is returned.");
3366    return( list() );
3367  }
3368  int sz=ncols(I);
3369  int i;
3370  int n=nvars(basering)-1;
3371  bigintmat REZ[1][n+1];
3372  int j;
3373  int szpr;
3374  list pr;
3375  int sgn=-1;
3376  for(i=1;i<=sz;i++)
3377  {
3378    sgn=-sgn;
3379    pr=prds(i,I);
3380    szpr=size(pr);
3381    for(j=1;j<=szpr;j++)
3382    {
3383      REZ=REZ+sgn*CSM_hypersurf(pr[j]);
3384    }
3385  }
3386  list rez;
3387  for(i=0;i<=n;i++)
3388  {
3389    rez=rez+list(REZ[1,i+1]);
3390  }
3391  return(rez);
3392}
3393example
3394{
3395  "EXAMPLE:";echo =2;
3396  // consider the projective plane with homogeneous coordinates x, y, z
3397  ring r = 0, (x, y, z), dp;
3398  // the Chern-Schwartz-MacPherson class of a smooth cubic:
3399  ideal I=x3+y3+z3;
3400  I;
3401  CSMA(I);
3402  // the Chern-Schwartz-MacPherson class of singular cubic
3403  // that is a union of 3 non-collinear lines:
3404  ideal J=x*y*z;
3405  J;
3406  CSMA(J);
3407  // the Chern-Schwartz-MacPherson class of singular cubic
3408  // that is a union of 3 lines passing through one point
3409  ideal K=x*y*(x+y);
3410  K;
3411  CSMA(K);
3412}
3413//-------------------------------------------------------------------------------------------
3414
3415proc EulerAff(ideal I)
3416"USAGE:   EulerAff(I);  I an ideal
3417RETURN:   integer
3418PURPOSE:  computes the Euler characteristic of the affine variety defined by I
3419EXAMPLE:  example EulerAff; shows an example
3420NOTE:
3421"
3422{
3423  int n=nvars(basering);
3424  def br@=basering; // remember the base ring
3425  ring r@ = create_ring(ring_list(basering)[1],"("+varstr(basering)+",homvar@)","dp","no_minpoly");
3426  ideal I=fetch(br@,I);
3427  ideal J=homog(I, homvar@);
3428  ideal JJ=J, homvar@;
3429  return( CSMA(J)[n+1]-CSMA(JJ)[n+1] );
3430}
3431example
3432{
3433  "EXAMPLE:";echo =2;
3434  ring r = 0, (x, y), dp;
3435  // compute the Euler characteristic of the affine elliptic curve y^2=x^3+x+1;
3436  ideal I=y2-x3-x-1;
3437  EulerAff(I);
3438}
3439//-------------------------------------------------------------------------------------------
3440
3441proc EulerProj(ideal I)
3442"USAGE:   EulerProj(I);  I an ideal
3443RETURN:   integer
3444PURPOSE:  computes the highest degree term of the Chern-Schwartz-MacPherson class
3445          of the variety defined by I, which equals the Euler characteristic
3446EXAMPLE:  example EulerProj; shows an example
3447NOTE:     uses CSMA(...)
3448"
3449{
3450  if( !homog(I) ) // if the ideal is not homogeneous
3451  {
3452    print("The ideal must be homogeneous, zero is returned.");
3453    return( int(0) );
3454  }
3455  int n=nvars(basering);
3456  return( CSMA(I)[n] );
3457}
3458example
3459{
3460  "EXAMPLE:";echo =2;
3461  // consider the projective plane with homogeneous coordinates x, y, z
3462  ring r = 0, (x, y, z), dp;
3463  // Euler characteristic of a smooth cubic:
3464  ideal I=x3+y3+z3;
3465  I;
3466  EulerProj(I);
3467  // Euler characteritic of 3 non-collinear lines:
3468  ideal J=x*y*z;
3469  J;
3470  EulerProj(J);
3471  // Euler characteristic of 3 lines passing through one point
3472  ideal K=x*y*(x+y);
3473  K;
3474  EulerProj(K);
3475}
3476//----------------------------------------------------------------------------------------
3477// The procedures below are for the internal usage only
3478//----------------------------------------------------------------------------------------
3479
3480static proc append_by_zeroes(int N, list c)
3481"USAGE:   append_by_zeroes( N, c);  N integer, c a list
3482RETURN:   list
3483PURPOSE:  appends by zeroes up to the length N
3484EXAMPLE:  example append_by_zeroes; shows an example
3485NOTE:
3486"
3487{
3488  int n=size(c);
3489  if(N>n) // if N is greater than the length of c, append c by zeroes up to the length N
3490  {
3491    int i;
3492    for(i=n+1;i<=N;i++)
3493    {
3494      c=c+list( poly(0) );
3495    }
3496  }
3497  return(c);
3498}
3499example
3500{
3501  "EXAMPLE:";echo =2;
3502  ring r = 0, (x, y, z), dp;
3503  list l=(x, y, z);
3504  //append the list by two zeroes and get a list of length 5
3505  print( append_by_zeroes(5, l) );
3506}
3507//-----------------------------------------------------------------------
3508
3509static proc is_integer(def r)
3510"USAGE:   is_integer(r);  r any type
3511RETURN:   1 or 0
3512PURPOSE:  checks whether r is of type int or bigint
3513EXAMPLE:  example is_integer; shows an example
3514NOTE: returns 1 if r is of type int or bigint, otherwise returns 0
3515"
3516{
3517  if( (typeof(r)=="int") || (typeof(r)=="bigint") )
3518  {
3519    return(1);
3520  }
3521  else
3522  {
3523    return(0);
3524  }
3525}
3526example
3527{
3528  "EXAMPLE:";echo =2;
3529  // test on int, bigint, poly
3530  ring r;
3531  int i=12;
3532  bigint j=16;
3533  poly f=x;
3534  print( is_integer(i) );
3535  print( is_integer(j) );
3536  print( is_integer(f) );
3537}
3538//------------------------------------------------------------------------------------
3539
3540static proc integer_list(list l)
3541"USAGE:   integer_list(l);  l list
3542RETURN:   list
3543PURPOSE:  gets the first positive ingerer entries of l, computes their maximum;
3544          used for adjusting the lists of optional parameters that are supposed to be integers
3545EXAMPLE:  example integer_list; shows an example
3546NOTE:     used in chWedge(...) and chSymm(...)
3547"
3548{
3549  int M=0;
3550  int n=size(l);
3551  if(n==0)
3552  {
3553    return(list(l, M));
3554  }
3555  // now n>0
3556  list rez; // the result will be computed here
3557  int i=1;
3558  while( is_integer( l[i] ) ) // take only the first integer entries of l
3559  {
3560    if(l[i]>0) // if they are positive
3561    {
3562      rez=rez+list( l[i] );
3563      if(l[i]>M) // adjust the maximum if necessary
3564      {
3565        M=l[i];
3566      }
3567      i++;
3568    }
3569    else // otherwise get out from the loop
3570    {
3571      break;
3572    }
3573  }
3574  return( list( rez, M)   );
3575}
3576example
3577{
3578  "EXAMPLE:";echo =2;
3579  // the first integer entries of 1,2,3,t are 1,2,3
3580  ring r=0,(t), ls;
3581  list l=1,2,3, t;
3582  print( integer_list(l) );
3583}
3584//---------------------------------------------------------------------------------------
3585
3586static proc appendToAll(list L, list A)
3587"USAGE:   appendToAll( L, A );  L list of lists, A list
3588RETURN:   list
3589PURPOSE:  appends A to every entry of L
3590EXAMPLE:  example appendToAll; shows an example
3591NOTE:
3592"
3593{
3594  int n=size(L);
3595  int i;
3596  for(i=1;i<=n;i++) // run through all elements of L
3597  {
3598    L[i]=L[i]+A; // and append A to each of them
3599  }
3600  return(L);
3601}
3602example
3603{
3604  "EXAMPLE:"; echo=2;
3605  // Consider two lists
3606  list l1, l2;
3607  l1=1,2;
3608  l2=3,4;
3609  // The first one is
3610  print(l1);
3611  // The second one is
3612  print(l2);
3613  // Now consider the list with entries l1 and l2
3614  list L= l1, l2;
3615  print(L);
3616  // and consider a list A
3617  list A = 7,9;
3618  print(A);
3619  // append A to all entries of L
3620  print( appendToAll(L, A) );
3621}
3622//---------------------------------------------------------------------------------------
3623
3624static proc listSame(int n, int k)
3625"USAGE:   listSame( n, k );  n integer, k non-negative integer
3626RETURN:   list
3627PURPOSE:  list with k entries each equal to n
3628EXAMPLE:  example listSame; shows an example
3629NOTE:     if k is negative or zero, the empty list is returned
3630"
3631{
3632  list rez;
3633  int i;
3634  for(i=1;i<=k;i++) // create a list with k entries, each equal to n
3635  {
3636    rez=rez+list(n);
3637  }
3638  return(rez);
3639}
3640example
3641{
3642  "EXAMPLE:"; echo=2;
3643  // list of 5 zeroes
3644  print( listSame(0, 5) );
3645}
3646//---------------------------------------------------------------------------------------
3647
3648static proc IJcoef(list I, list J)
3649"USAGE:   IJcoef( I, J);  J, J lists of integers
3650RETURN:   bigint
3651PURPOSE:  computes the coefficient used in the formula of Lascoux
3652EXAMPLE:  example IJcoef; shows an example
3653NOTE:     these coefficients are denoted (I, J) in the paper of Lascoux
3654"
3655{
3656  int m = size(I);
3657  if(m != size(J)) // if the sizes of I and J are different
3658  {
3659    // give a warning
3660    print("The sizes of the partitions are different!");
3661    print("Zero is returned.");
3662    return( bigint(0) ); // and return zero
3663  }
3664  // now the sizes of I and J are equal m
3665  int h, k;
3666  bigintmat M[m][m]; // construct the required matrix
3667  for(h=1; h<=m; h++)
3668  {
3669    for(k=1; k<=m; k++)
3670    {
3671      M[h,k] = binomial( I[k]+k-1, J[h]+h-1 );
3672    }
3673  }
3674  return( det(M) ); // and return its determinant
3675}
3676example
3677{
3678  "EXAMPLE:"; echo =2;
3679  // The coefficient corresponding to the partitions (1, 3, 4) and (0, 3, 3)
3680  list I = 1, 3, 4;
3681  list J = 1, 3, 3;
3682  print( IJcoef(I, J) );
3683}
3684//---------------------------------------------------------------------------------------
3685
3686static proc invertPart(list l)
3687"USAGE:   invertPart(I);  I list of integers (partition),
3688RETURN:   list of integers
3689PURPOSE:  inverts the ordering of the elements in the list
3690EXAMPLE:  example invertPart; shows an example
3691NOTE:
3692"
3693{
3694  list L;
3695  int sz=size(l);
3696  int i;
3697  for(i=sz;i>=1;i--)
3698  {
3699    L=L+list(l[i]);
3700  }
3701  return(L);
3702}
3703example
3704{
3705  "EXAMPLE:"; echo = 2;
3706  // Invert the ordering of elements in (3, 2, 1)
3707  list l = 3, 2, 1;
3708  print( invertPart(l) );
3709}
3710//---------------------------------------------------------------------------------------
3711
3712static proc LRmul(list I, list J)
3713"USAGE:   LRmul(x, y);  x, y lists of integers (partitions)
3714RETURN:   list of lists
3715PURPOSE:  computes the partitions z for which the Littlewood-Richardson
3716          coefficient c^z_{x,y} is non-zero together with that coefficient;
3717          partitions up to length r
3718EXAMPLE:  example LRmul; shows an example
3719NOTE:     uses LRmult(..) from lrcalc.lib, does the same,
3720          only uses the inverted ordering of the elements in the partition
3721"
3722{
3723  list rez=LRmult(invertPart(I), invertPart(J));
3724  int sz=size(rez);
3725  int i;
3726  for(i=1;i<=sz;i++)
3727  {
3728    rez[i][2]=invertPart(rez[i][2]);
3729  }
3730  return(rez);
3731}
3732example
3733{
3734  "EXAMPLE:"; echo = 2;
3735  // Compute the partitions z for which the Littlewood-Richardson coefficient
3736  // c^z_{x,y} is non-zero together with that coefficient
3737  // for x= (1, 2), y=(1, 2)
3738  list x = 1, 2;
3739  list y = 1, 2;
3740  print( LRmul(x, y) );
3741}
3742//---------------------------------------------------------------------------------------
3743
3744static proc hook(list I)
3745"USAGE:   hook(I);  I list of integers (partition),
3746RETURN:   bigint
3747PURPOSE:  computes the product of the hook lenhths of the partition I
3748EXAMPLE:  example hook; shows an example
3749NOTE:
3750"
3751{
3752  bigint rez=1;
3753  list dI= invertPart( dualPart(I) );
3754  I=invertPart( I );
3755  int szI=size(I);
3756  int szdI=size(dI);
3757  int i, j;
3758  for(i=1;i<=szI;i++)
3759  {
3760    for(j=1;j<=I[i];j++)
3761    {
3762      rez=rez*(I[i]+dI[j]-i-j+1);
3763    }
3764  }
3765  return(rez);
3766}
3767example
3768{
3769  "EXAMPLE:"; echo = 2;
3770  // compute the product of all hook lengths of the partition (1, 1, 3)
3771  list I = 1, 1, 3;
3772  print( hook(I) );
3773}
3774//---------------------------------------------------------------------------------------
3775
3776static proc apn0_int(int N, list c)
3777"USAGE:   apn0_int( N, c);  N integer, c list of integers (partition)
3778RETURN:   list of integers
3779PURPOSE:  appends by integer zeroes up to the length N
3780EXAMPLE:  example apn0_int; shows an example
3781NOTE:
3782"
3783{
3784  int n=size(c);
3785  if(N>n) // if N is greater than the length of c, append c by zeroes up to the length N
3786  {
3787    int i;
3788    for(i=n+1;i<=N;i++)
3789    {
3790      c=c+list( int(0) );
3791    }
3792  }
3793  return(c);
3794}
3795example
3796{
3797  "EXAMPLE:";echo =2;
3798  ring r = 0, (x, y, z), dp;
3799  list l=(1, 2, 3);
3800  //append the list by two zeroes and get a list of length 5
3801  print( apn0_int(5, l) );
3802}
3803//---------------------------------------------------------------------------------------
3804
3805static proc contentPoly(list I, list J, poly e)
3806"USAGE:   contentPoly(I, J, e);  L, M lists of integers (partitions),
3807          e polynomial
3808RETURN:   poly
3809PURPOSE:  computes the content polynomial of the skew partition corresponding to I>J
3810EXAMPLE:  example contentPoly; shows an example
3811NOTE:
3812"
3813{
3814  int i, j;
3815  int szI=size(I);
3816  I=invertPart(I);
3817  J=invertPart(J);
3818  J=apn0_int(szI, J);
3819  poly rez=1;
3820  for(i=1; i<=szI; i++)
3821  {
3822    for(j=J[i]+1; j<=I[i]; j++)
3823    {
3824      rez = rez*(e- i+j);
3825    }
3826  }
3827  return(rez);
3828}
3829example
3830{
3831  "EXAMPLE:"; echo = 2;
3832  // compute the content Polynomial of the skew partition
3833  // corresponding to  (1,2) > (0, 1) with respect to the variable x
3834  ring r = 0, (x), dp;
3835  list L=1,2;
3836  list M=0,1;
3837  print( contentPoly(L, M, x) );
3838}
3839//---------------------------------------------------------------------------------------
3840
3841static proc Pcoef(list L, list M, poly e, poly f)
3842"USAGE:   Pcoef(L, M, e, f);  L, M lists of integers (partitions),
3843          e, f polynomials
3844RETURN:   poly
3845PURPOSE:  computes the polynomial P_{L, M}(e, f) from the paper of Manivel
3846EXAMPLE:  example Pcoef; shows an example
3847NOTE:
3848"
3849{
3850  list P = LRmul(dualPart(L), M);
3851  int  sz=size(P);
3852  poly rez;
3853  //poly h;
3854  list T, DT;
3855  //bigint lrc;
3856  int i;
3857  for(i=1;i<=sz;i++)
3858  {
3859    T=P[i][2];
3860    DT=dualPart(T);
3861    //lrc=P[i][1];
3862    //h=contentPolyM(DT, L, e)*contentPoly(T, M, f);
3863    rez=rez+P[i][1]* contentPoly(DT, L, e)*contentPoly(T, M, f)/hook(DT);
3864  }
3865 return(rez);
3866}
3867example
3868{
3869  "EXAMPLE:"; echo = 2;
3870  // compute P_{L, M}(e, f) from the paper of Manivel
3871  // for L = (0,1) and M = (1, 1)
3872  ring r = 0, (e, f), dp;
3873  list L=1,2,3;
3874  list M=1,2;
3875  print( Pcoef(L, M, e, f) );
3876}
3877//---------------------------------------------------------------------------------------
3878
3879static proc max_deg(ideal I)
3880"USAGE:   max_deg(I);  I an ideal
3881RETURN:   integer
3882PURPOSE:  computes the maximal degree of the generators of I
3883EXAMPLE:  example max_deg; shows an example
3884NOTE:
3885"
3886{
3887  int rez=0;
3888  int i;
3889  int sz = ncols(I);
3890  for(i=1;i<=sz;i++)
3891  {
3892    rez=max(rez, deg(I[i]) );
3893  }
3894  return(rez);
3895}
3896example
3897{
3898  "EXAMPLE:";echo =2;
3899  // the maximal degree of the ideal in k[x, y]:
3900  ring r = 0, (x, y), dp;
3901  ideal I= x4, y7, x2y3;
3902  print(max_deg(I));
3903}
3904//-------------------------------------------------------------------------------------------
3905
3906static proc var_pow(int n)
3907"USAGE:   var_pow(n);  n an integer
3908RETURN:   ideal
3909PURPOSE:  computes the ideal generated by the n-th powers of the variables of the base ring
3910EXAMPLE:  example var_pow; shows an example
3911NOTE:
3912"
3913{
3914  ideal I=maxideal(1);
3915  int sz=ncols(I);
3916  int i;
3917  ideal J;
3918  for(i=1; i<=sz; i++)
3919  {
3920    J=J+ideal(I[i]^n);
3921  }
3922  return(J);
3923}
3924example
3925{
3926  "EXAMPLE:";echo =2;
3927  // the 3-rd powers of the variables in k[x, y]:
3928  ring r = 0, (x, y), dp;
3929  print(var_pow(3));
3930}
3931//-------------------------------------------------------------------------------------------
3932
3933static proc equal_deg(ideal I)
3934"USAGE:   equal_deg(I);  I an ideal
3935RETURN:   ideal
3936PURPOSE:  computes an ideal generated by elements of the same degree
3937          that defines the same projective subscheme as I
3938EXAMPLE:  example equal_deg; shows an example
3939NOTE:
3940"
3941{
3942  I=simplify(I, 8+2);
3943  int sz=ncols(I);
3944  int mxd=max_deg(I);
3945  int i;
3946  ideal J;
3947  for(i=1;i<=sz;i++)
3948  {
3949    J=J+I[i]*var_pow( mxd-deg(I[i]) );
3950  }
3951
3952  return(sort( simplify(J, 8+2) )[1]);
3953}
3954example
3955{
3956  "EXAMPLE:"; echo=2;
3957  // change the ideal (x, y^2) in k[x, y, z]:
3958  ring r = 0, (x, y, z), dp;
3959  ideal I=x, y*z;
3960  // the ideal defines a two points subscheme in the projective plane
3961  // and is generated by elements of different degrees
3962  print(I);
3963  ideal J=equal_deg(I);
3964  // now the ideal is generated by elements of degree 2
3965  // and defines the same subscheme in the projective plane
3966  J;
3967  // notice that both ideals have the same saturation
3968  // with respect to the irrelevant ideal (x, y, z)
3969  // the saturation of the initial ideal coincides with the ideal itself
3970  sat(I, maxideal(1))[1];
3971  // the saturation of the modified ideal
3972  sat(J, maxideal(1))[1];
3973}
3974//-------------------------------------------------------------------------------------------
3975
3976static proc CSM_hypersurf(poly f)
3977"USAGE:   CSM_hypersurf(f);  f a polynomial
3978RETURN:   list of integers
3979PURPOSE:  computes the Chern-Schwartz-MacPherson classes of the hypersurface defined by f
3980EXAMPLE:  example CSM_hypersurf; shows an example
3981NOTE:
3982"
3983{
3984  ideal I=jacob(f);
3985  I=simplify(I, 8+2); // ignore repetitions and zero generators
3986  I=sort(I)[1]; // sort the generators, it speeds up the computations
3987  int degGen=deg(I[1]); // the degree of the generators of the Jacobian ideal
3988  int i;
3989  int n=nvars(basering)-1; // the dimension of the projective space
3990  bigintmat REZ[1][n+1];
3991  if(degGen==-1) // if the Jacobian ideal is zero
3992  {
3993    for(i=0;i<=n;i++)
3994    {
3995      REZ[1,i+1]=binomial(n+1,i);
3996    }
3997    return(REZ);
3998  }
3999  //TODO need to check the zero ideal and I==1;
4000  int sz=ncols(I);
4001  def br@=basering; // remember the base ring
4002  list l15 = ringlist(basering)[2];
4003  for (int ii = 1; ii <= sz; ii++)
4004  {
4005   l15[size(l15)+1] = "t@("+string(ii)+")";
4006  }
4007  l15[size(l15)+1] = "u@";
4008  ring r@ = create_ring(ring_list(basering)[1], l15, "dp", "no_minpoly");
4009  ideal I=fetch(br@,I);
4010  ideal J(0..n);
4011  for(i=1; i<=sz; i++)
4012  {
4013    J(0)=J(0) + ideal( t@(i)-u@*I[i] );
4014  }
4015  J(0)=eliminate(J(0), u@);
4016  ideal T=t@(1..sz);
4017  for(i=1;i<=n;i++)
4018  {
4019    J(i) = sat( random_hypersurf(J(i-1), T), T )[1];
4020  }
4021  poly prd=product(T);
4022  poly cl;
4023  poly mlt;
4024  for(i=0;i<=n;i++)
4025  {
4026    cl=cl+  mult( std(eliminate( J(i),  prd)) ) *(-u@)^i*(1+u@)^(n-i);
4027  }
4028  cl=(1+u@)^(n+1)-cl;
4029  poly resPoly=NF( cl, u@^(n+1) );
4030  matrix cf=coeffs(resPoly, u@);
4031  for(i=0;i<=n;i++)
4032  {
4033    if( i < nrows(cf) )
4034    {
4035      REZ[1,i+1]=int(cf[i+1,1]);
4036    }
4037    else
4038    {
4039      REZ[1,i+1]=int(0);
4040    }
4041  }
4042  return(REZ);
4043}
4044example
4045{
4046  "EXAMPLE:";echo =2;
4047  // consider the projective plane with homogeneous coordinates x, y, z
4048  ring r = 0, (x, y, z), dp;
4049  // the Chern-Schwartz-MacPherson class of a smooth cubic:
4050  poly f=x3+y3+z3;
4051  f;
4052  CSM_hypersurf(f);
4053  // the Chern-Schwartz-MacPherson class of singular cubic
4054  // that is a union of 3 non-collinear lines:
4055  poly g=x*y*z;
4056  g;
4057  CSM_hypersurf(g);
4058  // the Chern-Schwartz-MacPherson class of singular cubic
4059  // that is a union of 3 lines passing through one point
4060  poly h=x*y*(x+y);
4061  h;
4062  CSM_hypersurf(h);
4063}
4064//-------------------------------------------------------------------------------------------
4065
4066static proc random_hypersurf(ideal I, ideal V)
4067"USAGE:   random_hypersurf(I, V);  I, V ideals
4068RETURN:   ideal
4069PURPOSE:  computes the sum of I with the ideal generated by a random
4070          linear combination of the generators of V such that the dimension decreases
4071EXAMPLE:  example random_hypersurf; shows an example
4072NOTE:     if the ideal I=1 (the whole ring), then I is returned
4073"
4074{
4075  ideal H;
4076  ideal J;
4077 // if(isSubModule(ideal(1), I)) // if I equals 1 (the whole ring);
4078  if( is_zero(I) )
4079  {
4080    return(I);
4081  }
4082  // otherwise
4083  int ok=0;
4084  int ntries; // number of tries
4085  while( !ok ) // give two tries for every b in randomid(V, 1, b)
4086  {
4087    H=randomid(V, 1, ntries div 2 +1);
4088    ntries++; // increase by 1
4089    if( isSubModule( quotient(I, ideal(H) ), I) )
4090    {
4091      J=I + H;
4092      ok=1;
4093    }
4094  }
4095  return(J);
4096}
4097example
4098{
4099  "EXAMPLE:";echo =2;
4100  // Consider an ideal in  k[x, y, z, s, t] and find its intersection with a general hyperplane
4101  // given by as+bt=0
4102  ring r = 0, (x, y, z, s, t), dp;
4103  ideal I=x2, yz, s+t;
4104  I;
4105  ideal V= s, t;
4106  V;
4107  // the ideal of the intersection with the random general hyperplane
4108  random_hypersurf(I, V);
4109}
4110//-------------------------------------------------------------------------------------------
4111
4112static proc prds(int n, def l)
4113"USAGE:   prds(n, l);  n an integer, l list of polynomials or ideal
4114RETURN:   list of polynomials
4115PURPOSE:  computes all possible products of length n (without repetitions) of the entries of l
4116EXAMPLE:  example prds; shows an example
4117NOTE:
4118"
4119{
4120  int sz;
4121  if(typeof(l)=="ideal")
4122  {
4123    sz=ncols(l);
4124  }
4125  else
4126  {
4127    sz=size(l);
4128  }
4129  if( (n>sz)||(sz==0)||(n<0) )
4130  {
4131    return( list() );
4132  }
4133  // otherwise
4134  if(n==0)
4135  {
4136    return( list(int(1)) );
4137  }
4138  if(sz==n)
4139  {
4140    return(product(l));
4141  }
4142  list L, LL, ll;
4143  ll=l[2..sz];
4144  poly f=l[1];
4145  L=prds(n, ll );
4146  LL=prds(n-1,ll);
4147  int i;
4148  sz=size(LL);
4149  for(i=1;i<=sz;i++)
4150  {
4151    LL[i]=f*LL[i];
4152  }
4153  return(L+LL);
4154}
4155example
4156{
4157  "EXAMPLE:";echo =2;
4158  ring r = 0, (x, y, z, w), dp;
4159  // compute all possible 2-products between the variables x,y,z,w
4160  list l=x,y,z,w;
4161  prds(2, l);
4162  // compute all possible 3-products between the variables x,y,z,w
4163  ideal I=x,y,z,w;
4164  prds(3, l);
4165}
4166//-------------------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.