source: git/Singular/LIB/chern.lib @ 699fed

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