source: git/Singular/LIB/polymake.lib @ e861ae

spielwiese
Last change on this file since e861ae was e861ae, checked in by Hans Schoenemann <hannes@…>, 8 years ago
fix: doc/libs for gfanlib.so
  • Property mode set to 100644
File size: 83.6 KB
Line 
1version="version polymake.lib 4.0.0.0 Jun_2013 ";
2category="Tropical Geometry";
3info="
4LIBRARY:   polymake.lib    Computations with polytopes and fans,
5                           interface to polymake and TOPCOM
6AUTHOR:    Thomas Markwig,  email: keilen@mathematik.uni-kl.de
7
8WARNING:
9   Most procedures will not work unless polymake or topcom is installed and
10   if so, they will only work with the operating system LINUX!
11   For more detailed information see IMPORTANT NOTE respectively consult the
12   help string of the procedures.
13
14   The conventions used in this library for polytopes and fans, e.g. the
15   length and labeling of their vertices resp. rays, differs from the conventions
16   used in polymake and thus from the conventions used in the polymake
17   extension polymake.so of Singular. We recommend to use the newer polymake.so
18   whenever possible.
19
20IMPORTANT NOTE:
21@texinfo
22   Even though this is a Singular library for computing polytopes and fans
23   such as the Newton polytope or the Groebner fan of a polynomial, most of
24   the hard computations are NOT done by Singular but by the program
25@* - polymake by Ewgenij Gawrilow, TU Berlin and Michael Joswig, TU Darmstadt
26   (see @uref{http://www.polymake.org/}),
27@* respectively (only in the procedure triangulations) by the program
28@* - topcom by Joerg Rambau, Universitaet Bayreuth (see
29     @uref{http://www.rambau.wm.uni-bayreuth.de/TOPCOM/});
30@* this library should rather be seen as an interface which allows to use a
31   (very limited) number of options which polymake respectively topcom offers
32   to compute with polytopes and fans and to make the results available in
33   Singular for further computations;
34   moreover, the user familiar with Singular does not have to learn the syntax
35   of polymake or topcom, if the options offered here are sufficient for his
36   purposes.
37@* Note, though, that the procedures concerned with planar polygons are
38   independent of both, polymake and topcom.
39@end texinfo
40
41PROCEDURES USING POLYMAKE:
42  polymakePolytope()  computes the vertices of a polytope using polymake
43  newtonPolytopeP()    computes the Newton polytope of a polynomial
44  newtonPolytopeLP()  computes the lattice points of the Newton polytope
45  normalFanL()         computes the normal fan of a polytope
46  groebnerFanP()       computes the Groebner fan of a polynomial
47
48PROCEDURES USING TOPCOM:
49  triangulations()    computes all triangulations of a marked polytope
50  secondaryPolytope() computes the secondary polytope of a marked polytope
51
52PROCEDURES USING POLYMAKE AND TOPCOM:
53  secondaryFan()      computes the secondary fan of a marked polytope
54
55PROCEDURES CONERNED WITH PLANAR POLYGONS:
56  cycleLength()    computes the cycleLength of cycle
57  splitPolygon()   splits a marked polygon into vertices, facets, interior points
58  eta()            computes the eta-vector of a triangulation
59  findOrientedBoundary()  computes the boundary of a convex hull
60  cyclePoints()    computes lattice points connected to some lattice point
61  latticeArea()    computes the lattice area of a polygon
62  picksFormula()   computes the ingrediants of Pick's formula for a polygon
63  ellipticNF()     computes the normal form of an elliptic polygon
64  ellipticNFDB()   displays the 16 normal forms of elliptic polygons
65
66KEYWORDS:    polytope; fan; secondary fan; secondary polytope; polymake;
67             Newton polytope; Groebner fan
68";
69
70////////////////////////////////////////////////////////////////////////////////
71/// Auxilary Static Procedures in this Library
72////////////////////////////////////////////////////////////////////////////////
73/// - scalarproduct
74/// - intmatcoldelete
75/// - intmatconcat
76/// - sortlist
77/// - minInList
78/// - stringdelete
79/// - abs
80/// - commondenominator
81/// - maxPosInIntvec
82/// - maxPosInIntmat
83/// - sortintvec
84/// - matrixtointmat
85////////////////////////////////////////////////////////////////////////////////
86
87////////////////////////////////////////////////////////////////////////////////
88LIB "poly.lib";
89LIB "linalg.lib";
90LIB "random.lib";
91////////////////////////////////////////////////////////////////////////////////
92
93static proc mod_init ()
94{
95  LIB "customstd.so";
96  LIB "gfanlib.so";
97  LIB "polymake.so";
98}
99
100/////////////////////////////////////////////////////////////////////////////
101/// PROCEDURES USING POLYMAKE
102/////////////////////////////////////////////////////////////////////////////
103
104proc polymakePolytope (intmat points)
105"USAGE:  polymakePolytope(points);   polytope intmat
106ASSUME:  each row of points gives the coordinates of a lattice point of a
107         polytope with their affine coordinates as given by the output of
108         secondaryPolytope
109PURPOSE: the procedure calls polymake to compute the vertices of the polytope
110         as well as its dimension and information on its facets
111RETURN:  list, L with four entries
112@*            L[1] : an integer matrix whose rows are the coordinates of vertices
113                     of the polytope
114@*            L[2] : the dimension of the polytope
115@*            L[3] : a list whose ith entry explains to which vertices the
116                     ith vertex of the Newton polytope is connected
117                     -- i.e. L[3][i] is an integer vector and an entry k in
118                        there means that the vertex L[1][i] is connected to the
119                        vertex L[1][k]
120@*            L[4] : an matrix of type bigintmat whose rows mulitplied by
121                     (1,var(1),...,var(nvar)) give a linear system of equations
122                     describing the affine hull of the polytope,
123                     i.e. the smallest affine space containing the polytope
124NOTE: -  for its computations the procedure calls the program polymake by
125         Ewgenij Gawrilow, TU Berlin and Michael Joswig, TU Darmstadt;
126         it therefore is necessary that this program is installed in order
127         to use this procedure;
128         see http://www.polymake.org/
129@*    -  note that in the vertex edge graph we have changed the polymake
130         convention which starts indexing its vertices by zero while we start
131         with one !
132EXAMPLE: example polymakePolytope;   shows an example"
133{
134  // add a first column to polytope as homogenising coordinate
135  points=intmatAddFirstColumn(points,"points");
136  polytope polytop=polytopeViaPoints(points);
137  list graph=vertexAdjacencyGraph(polytop)[2];
138  int i,j;
139  for (i=1;i<=size(graph);i++)
140  {
141    for (j=1;j<=size(graph[i]);j++)
142    {
143      graph[i][j]=graph[i][j]+1;
144    }
145  }
146  return(list(intmatcoldelete(vertices(polytop),1),dimension(polytop),graph,equations(polytop)));
147}
148example
149{
150   "EXAMPLE:";
151   echo=2;
152   // the lattice points of the unit square in the plane
153   list points=intvec(0,0),intvec(0,1),intvec(1,0),intvec(1,1);
154   // the secondary polytope of this lattice point configuration is computed
155   intmat secpoly=secondaryPolytope(points)[1];
156   list np=polymakePolytope(secpoly);
157   // the vertices of the secondary polytope are:
158   np[1];
159   // its dimension is
160   np[2];
161   // np[3] contains information how the vertices are connected to each other,
162   // e.g. the first vertex (number 0) is connected to the second one
163   np[3][1];
164   // the affine hull has the equation
165   ring r=0,x(1..4),dp;
166   matrix M[5][1]=1,x(1),x(2),x(3),x(4);
167   intmat(np[4])*M;
168}
169
170/////////////////////////////////////////////////////////////////////////////
171
172proc newtonPolytopeP (poly f)
173"USAGE: newtonPolytopeP(f);  f poly
174RETURN: list, L with four entries
175@*            L[1] : an integer matrix whose rows are the coordinates of vertices
176                     of the Newton polytope of f
177@*            L[2] : the dimension of the Newton polytope of f
178@*            L[3] : a list whose ith entry explains to which vertices the
179                     ith vertex of the Newton polytope is connected
180                     -- i.e. L[3][i] is an integer vector and an entry k in
181                        there means that the vertex L[1][i] is
182                        connected to the vertex L[1][k]
183@*            L[4] : an matrix of type bigintmat whose rows mulitplied by
184                     (1,var(1),...,var(nvar)) give a linear system of equations
185                     describing the affine hull of the Newton polytope, i.e. the
186                     smallest affine space containing the Newton polytope
187NOTE: -  if we replace the first column of L[4] by zeros, i.e. if we move
188         the affine hull to the origin, then we get the equations for the
189         orthogonal complement of the linearity space of the normal fan dual
190         to the Newton polytope, i.e. we get the EQUATIONS that
191         we need as input for polymake when computing the normal fan
192@*    -  the procedure calls for its computation polymake by Ewgenij Gawrilow,
193         TU Berlin and Michael Joswig, so it only works if polymake is installed;
194         see http://www.polymake.org/
195EXAMPLE: example newtonPolytopeP;   shows an example"
196{
197  int i,j;
198  // compute the list of exponent vectors of the polynomial,
199  // which are the lattice points
200  // whose convex hull is the Newton polytope of f
201  intmat exponents[size(f)][nvars(basering)];
202  while (f!=0)
203  {
204    i++;
205    exponents[i,1..nvars(basering)]=leadexp(f);
206    f=f-lead(f);
207  }
208  // call polymakePolytope with exponents
209  return(polymakePolytope(exponents));
210}
211example
212{
213   "EXAMPLE:";
214   echo=2;
215   ring r=0,(x,y,z),dp;
216   matrix M[4][1]=1,x,y,z;
217   poly f=y3+x2+xy+2xz+yz+z2+1;
218   // the Newton polytope of f is
219   list np=newtonPolytopeP(f);
220   // the vertices of the Newton polytope are:
221   np[1];
222   // its dimension is
223   np[2];
224   // np[3] contains information how the vertices are connected to each other,
225   // e.g. the first vertex (number 0) is connected to the second, third and
226   //      fourth vertex
227   np[3][1];
228   //////////////////////////
229   f=x2-y3;
230   // the Newton polytope of f is
231   np=newtonPolytopeP(f);
232   // the vertices of the Newton polytope are:
233   np[1];
234   // its dimension is
235   np[2];
236   // the Newton polytope is contained in the affine space given
237   //     by the equations
238   intmat(np[4])*M;
239}
240
241/////////////////////////////////////////////////////////////////////////////
242
243proc newtonPolytopeLP (poly f)
244"USAGE:  newtonPolytopeLP(f);  f poly
245RETURN: list, the exponent vectors of the monomials occuring in f,
246              i.e. the lattice points of the Newton polytope of f
247EXAMPLE: example newtonPolytopeLP;   shows an example"
248{
249  list np;
250  int i=1;
251  while (f!=0)
252  {
253    np[i]=leadexp(f);
254    f=f-lead(f);
255    i++;
256  }
257  return(np);
258}
259example
260{
261   "EXAMPLE:";
262   echo=2;
263   ring r=0,(x,y,z),dp;
264   poly f=y3+x2+xy+2xz+yz+z2+1;
265   // the lattice points of the Newton polytope of f are
266   newtonPolytopeLP(f);
267}
268
269/////////////////////////////////////////////////////////////////////////////
270
271proc normalFanL (def vertices, def affinehull,list graph,int er,list #)
272"USAGE:  normalFanL (vert,aff,graph,rays,[,#]);   vert,aff intmat,  graph list, rays int, # string
273ASSUME:  - vert is an integer matrix whose rows are the coordinate of
274           the vertices of a convex lattice polytope;
275@*       - aff describes the affine hull of this polytope, i.e.
276           the smallest affine space containing it, in the following sense:
277           denote by n the number of columns of vert, then multiply aff by
278           (1,x(1),...,x(n)) and set the resulting terms to zero in order to
279           get the equations for the affine hull;
280@*       - the ith entry of graph is an integer vector describing to which
281           vertices the ith vertex is connected, i.e. a k as entry means that
282           the vertex vert[i] is connected to vert[k];
283@*       - the integer rays is either one (if the extreme rays should be
284           computed) or zero (otherwise)
285RETURN:  list, the ith entry of L[1] contains information about the cone in the
286               normal fan dual to the ith vertex of the polytope
287@*             L[1][i][1] = integer matrix representing the inequalities which
288                            describe the cone dual to the ith vertex
289@*             L[1][i][2] = a list which contains the inequalities represented
290                            by L[i][1] as a list of strings, where we use the
291                            variables x(1),...,x(n)
292@*             L[1][i][3] = only present if 'er' is set to 1; in that case it is
293                            an interger matrix whose rows are the extreme rays
294                            of the cone
295@*             L[2] = is an integer matrix whose rows span the linearity space
296                      of the fan, i.e. the linear space which is contained in
297                      each cone
298NOTE:    - the procedure calls for its computation polymake by Ewgenij Gawrilow,
299           TU Berlin and Michael Joswig, so it only works if polymake is
300           installed;
301           see http://www.polymake.org/
302@*       - in the optional argument # it is possible to hand over other names
303           for the variables to be used -- be careful, the format must be correct
304           and that is not tested, e.g. if you want the variable names to be
305           u00,u10,u01,u11 then you must hand over the string u11,u10,u01,u11
306EXAMPLE: example normalFanL;   shows an example"
307{
308  if (typeof(affinehull) != "intmat" && typeof (affinehull) != "bigintmat")
309  {
310    ERROR("normalFanL: input affinehull has to be either intmat or bigintmat");
311    list L;
312    return (L);
313  }
314  list ineq; // stores the inequalities of the cones
315  int i,j,k;
316  // we work over the following ring
317  execute("ring ineqring=0,x(1.."+string(ncols(vertices))+"),lp;");
318  string greatersign=">";
319  // create the variable names
320  if (size(#)>0)
321  {
322    if (typeof(#[1])=="string")
323    {
324      kill ineqring;
325      execute("ring ineqring=0,("+#[1]+"),lp;");
326    }
327    if (size(#)>1)
328    {
329      greatersign="<";
330    }
331  }
332  //////////////////////////////////////////////////////////////////
333  // Compute first the inequalities of the cones
334  //////////////////////////////////////////////////////////////////
335  matrix VAR[1][ncols(vertices)]=maxideal(1);
336  matrix EXP[ncols(vertices)][1];
337  poly p,pl,pr;
338  // consider all vertices of the polytope
339  for (i=1;i<=nrows(vertices);i++)
340  {
341    // first we produce for each vertex in the polytope
342    // the inequalities describing the dual cone in the normal fan
343    list pp;  // contain strings representing the inequalities
344              // describing the normal cone
345    if (typeof (vertices) == "intmat")
346    {
347      intmat ie[size(graph[i])][ncols(vertices)]; // contains the inequalities
348    }                                             // as rows
349    if (typeof (vertices) == "bigintmat")
350    {
351      bigintmat ie[size(graph[i])][ncols(vertices)]; // contains the inequalities
352    }                                                // as rows
353    // consider all the vertices to which the ith vertex in the
354    // polytope is connected by an edge
355    for (j=1;j<=size(graph[i]);j++)
356    {
357      // produce the vector ie_j pointing from the jth vertex to the ith vertex;
358      // this will be the jth inequality for the cone in the normal fan dual to
359      // the ith vertex
360      ie[j,1..ncols(vertices)]=vertices[i,1..ncols(vertices)]-vertices[graph[i][j],1..ncols(vertices)];
361      EXP=ie[j,1..ncols(vertices)];
362      // build a linear polynomial with the entries of ie_j as coefficients
363      p=(VAR*EXP)[1,1];
364      pl,pr=0,0;
365      // separate the terms with positive coefficients in p from
366      // those with negative coefficients
367      for (k=1;k<=size(p);k++)
368      {
369        if (leadcoef(p[k])<0)
370        {
371          pr=pr-p[k];
372        }
373        else
374        {
375          pl=pl+p[k];
376        }
377      }
378      // build the string which represents the jth inequality
379      // for the cone dual to the ith vertex
380      // as polynomial inequality of type string, and store this
381      // in the list pp as jth entry
382      pp[j]=string(pl)+" "+greatersign+" "+string(pr);
383    }
384    // all inequalities for the ith vertex are stored in the list ineq
385    ineq[i]=list(ie,pp);
386    kill ie,pp; // kill certain lists
387  }
388  // remove the first column of affine hull to compute the linearity space
389  bigintmat linearity[1][ncols(vertices)];
390  if (nrows(affinehull)>0)
391  {
392    linearity=intmatcoldelete(affinehull,1);
393  }
394  //////////////////////////////////////////////////////////////////
395  // Compute next the extreme rays of the cones
396  //////////////////////////////////////////////////////////////////
397  if (er==1)
398  {
399    list extremerays; // keeps the result
400    cone kegel;
401    bigintmat linearspan=intmatAddFirstColumn(linearity,"rays");
402    intmat M; // the matrix keeping the inequalities
403    for (i=1;i<=size(ineq);i++)
404    {
405      kegel=coneViaInequalities(intmatAddFirstColumn(ineq[i][1],"rays"),linearspan);
406      extremerays[i]=intmatcoldelete(rays(kegel),1);
407    }
408    for (i=1;i<=size(ineq);i++)
409    {
410      ineq[i]=ineq[i]+list(extremerays[i]);
411    }
412  }
413  // get the linearity space
414  return(list(ineq,linearity));
415}
416example
417{
418   "EXAMPLE:";
419   echo=2;
420   ring r=0,(x,y,z),dp;
421   matrix M[4][1]=1,x,y,z;
422   poly f=y3+x2+xy+2xz+yz+z2+1;
423   // the Newton polytope of f is
424   list np=newtonPolytopeP(f);
425   // the Groebner fan of f, i.e. the normal fan of the Newton polytope
426   list gf=normalFanL(np[1],np[4],np[3],1,"x,y,z");
427   // the number of cones in the Groebner fan of f is:
428   size(gf[1]);
429   // the inequalities of the first cone as matrix are:
430   print(gf[1][1][1]);
431   // the inequalities of the first cone as string are:
432   print(gf[1][1][2]);
433   // the rows of the following matrix are the extreme rays of the first cone:
434   print(gf[1][1][3]);
435   // each cone contains the linearity space spanned by:
436   print(gf[2]);
437}
438
439/////////////////////////////////////////////////////////////////////////////
440
441proc groebnerFanP (poly f)
442"USAGE:  groebnerFanP(f);  f poly
443RETURN:  list, the ith entry of L[1] contains information about the ith cone
444               in the Groebner fan dual to the ith vertex in the Newton
445               polytope of the f
446@*             L[1][i][1] = integer matrix representing the inequalities
447                            which describe the cone
448@*             L[1][i][2] = a list which contains the inequalities represented
449                            by L[1][i][1] as a list of strings
450@*             L[1][i][3] = an interger matrix whose rows are the extreme rays
451                            of the cone
452@*             L[2] = is an integer matrix whose rows span the linearity space
453                      of the fan, i.e. the linear space which is contained
454                      in each cone
455@*             L[3] = the Newton polytope of f in the format of the procedure
456                      newtonPolytopeP
457@*             L[4] = integer matrix where each row represents the exponent
458                      vector of one monomial occuring in the input polynomial
459NOTE: - if you have already computed the Newton polytope of f then you might want
460        to use the procedure normalFanL instead in order to avoid doing costly
461        computation twice
462@*    - the procedure calls for its computation polymake by Ewgenij Gawrilow,
463        TU Berlin and Michael Joswig, so it only works if polymake is installed;
464        see http://www.polymake.org/
465EXAMPLE: example groebnerFanP;   shows an example"
466{
467  int i,j;
468  // compute the list of exponent vectors of the polynomial, which are
469  // the lattice points whose convex hull is the Newton polytope of f
470  intmat exponents[size(f)][nvars(basering)];
471  while (f!=0)
472  {
473    i++;
474    exponents[i,1..nvars(basering)]=leadexp(f);
475    f=f-lead(f);
476  }
477  // call polymakePolytope with exponents
478  list newtonp=polymakePolytope(exponents);
479  // get the variables as string
480  string variablen;
481  for (i=1;i<=nvars(basering);i++)
482  {
483    variablen=variablen+string(var(i))+",";
484  }
485  variablen=variablen[1,size(variablen)-1];
486  // call normalFanL in order to compute the Groebner fan
487  list gf=normalFanL(newtonp[1],newtonp[4],newtonp[3],1,variablen);
488  // append newtonp to gf
489  gf[3]=newtonp;
490  // append the exponent vectors to gf
491  gf[4]=exponents;
492  return(gf);
493}
494example
495{
496   "EXAMPLE:";
497   echo=2;
498   ring r=0,(x,y,z),dp;
499   matrix M[4][1]=1,x,y,z;
500   poly f=y3+x2+xy+2xz+yz+z2+1;
501   // the Newton polytope of f is
502   list gf=groebnerFanP(f);
503   // the exponent vectors of f are ordered as follows
504   gf[4];
505   // the first cone of the groebner fan has the inequalities
506   gf[1][1][1];
507   // as a string they look like
508   gf[1][1][2];
509   // and it has the extreme rays
510   print(gf[1][1][3]);
511   // the linearity space is spanned by
512   print(gf[2]);
513   // the vertices of the Newton polytope are:
514   gf[3][1];
515   // its dimension is
516   gf[3][2];
517   // np[3] contains information how the vertices are connected to each other,
518   // e.g. the 1st vertex is connected to the 2nd, 3rd and 4th vertex
519   gf[3][3][1];
520}
521
522
523
524///////////////////////////////////////////////////////////////////////////////
525/// PROCEDURES USING TOPCOM
526///////////////////////////////////////////////////////////////////////////////
527
528proc triangulations (list polygon,list #)
529"USAGE:  triangulations(polygon[,#]); list polygon, list #
530ASSUME:  polygon is a list of integer vectors of the same size representing
531         the affine coordinates of the lattice points
532PURPOSE: the procedure considers the marked polytope given as the convex hull of
533         the lattice points and with these lattice points as markings; it then
534         computes all possible triangulations of this marked polytope
535RETURN:  list, each entry corresponds to one triangulation and the ith entry is
536               itself a list of integer vectors of size three, where each integer
537               vector defines one triangle in the triangulation by telling which
538               points of the input are the vertices of the triangle
539NOTE:- the procedure calls for its computations the program points2triangs
540       from the program topcom by Joerg Rambau, Universitaet Bayreuth; it
541       therefore is necessary that this program is installed in order to use
542       this  procedure; see http://www.rambau.wm.uni-bayreuth.de/TOPCOM/);
543@*   - if you only want to have the regular triangulations the procedure should
544       be called with the string 'regular' as optional argument
545@*   - the procedure creates the files /tmp/triangulationsinput and
546       /tmp/triangulationsoutput;
547       the former is used as input for points2triangs and the latter is its
548       output containing the triangulations of corresponding to points in the
549       format of points2triangs; if you wish to use this for further
550       computations with topcom, you have to call the procedure with the
551       string 'keepfiles' as optional argument
552@*   - note that an integer i in an integer vector representing a triangle
553       refers to the ith lattice point, i.e. polygon[i]; this convention is
554       different from TOPCOM's convention, where i would refer to the i-1st
555       lattice point
556EXAMPLE: example triangulations;   shows an example"
557{
558  int i,j;
559  // check for optional arguments
560  int regular,keepfiles;
561  if (size(#)>0)
562  {
563    for (i=1;i<=size(#);i++)
564    {
565      if (typeof(#[i])=="string")
566      {
567        if (#[i]=="keepfiles")
568        {
569          keepfiles=1;
570        }
571        if (#[i]=="regular")
572        {
573          regular=1;
574        }
575      }
576    }
577  }
578  // prepare the input for points2triangs by writing the input polygon in the
579  // necessary format
580  string spi="[";
581  for (i=1;i<=size(polygon);i++)
582  {
583    polygon[i][size(polygon[i])+1]=1;
584    spi=spi+"["+string(polygon[i])+"]";
585    if (i<size(polygon))
586    {
587      spi=spi+",";
588    }
589  }
590  spi=spi+"]";
591  write(":w /tmp/triangulationsinput",spi);
592  // call points2triangs
593  if (regular==1) // compute only regular triangulations
594  {
595    system("sh","cd /tmp; points2triangs --regular < triangulationsinput > triangulationsoutput");
596  }
597  else // compute all triangulations
598  {
599    system("sh","cd /tmp; points2triangs < triangulationsinput > triangulationsoutput");
600  }
601  string p2t=read("/tmp/triangulationsoutput"); // takes result of points2triangs
602  // delete the tmp-files, if no second argument is given
603  if (keepfiles==0)
604  {
605    system("sh","cd /tmp; rm -f triangulationsinput; rm -f triangulationsoutput");
606  }
607  // preprocessing of p2t if points2triangs is version >= 0.15
608  // brings p2t to the format of version 0.14
609  string np2t; // takes the triangulations in Singular format
610  for (i=1;i<=size(p2t)-2;i++)
611  {
612    if ((p2t[i]==":") and (p2t[i+1]=="=") and (p2t[i+2]=="["))
613    {
614      np2t=np2t+p2t[i]+p2t[i+1];
615      i=i+3;
616      while (p2t[i]!=":")
617      {
618        i=i+1;
619      }
620    }
621    else
622    {
623      if ((p2t[i]=="]") and (p2t[i+1]==";"))
624      {
625        np2t=np2t+p2t[i+1];
626        i=i+1;
627      }
628      else
629      {
630        np2t=np2t+p2t[i];
631      }
632    }
633  }
634  if (p2t[size(p2t)-1]=="]")
635  {
636    np2t=np2t+p2t[size(p2t)];
637  }
638  else
639  {
640    if (np2t[size(np2t)]!=";")
641    {
642      np2t=np2t+p2t[size(p2t)-1]+p2t[size(p2t)];
643    }
644  }
645  p2t=np2t;
646  np2t="";
647  // transform the points2triangs output of version 0.14 into Singular format
648  for (i=1;i<=size(p2t);i++)
649  {
650    if (p2t[i]=="=")
651    {
652      np2t=np2t+p2t[i]+"list(";
653      i++;
654    }
655    else
656    {
657      if (p2t[i]!=":")
658      {
659        if ((p2t[i]=="}") and (p2t[i+1]=="}"))
660        {
661          np2t=np2t+"))";
662          i++;
663        }
664        else
665        {
666          if (p2t[i]=="{")
667          {
668            np2t=np2t+"intvec(";
669          }
670          else
671          {
672            if (p2t[i]=="}")
673            {
674              np2t=np2t+")";
675            }
676            else
677            {
678              if (p2t[i]=="[")
679              {
680                // in Topcom version 17.4 (and maybe also in earlier versions) the list
681                // of triangulations is indexed starting with index 0, in Singular
682                // we have to start with index 1
683                np2t=np2t+p2t[i]+"1+";
684              }
685              else
686              {
687                np2t=np2t+p2t[i];
688              }
689            }
690          }
691        }
692      }
693    }
694  }
695  list T;
696  execute(np2t);
697  // depending on the version of Topcom, the list T has or has not an entry T[1]
698  // if it has none, the entry should be removed
699  while (typeof(T[1])=="none")
700  {
701    T=delete(T,1);
702  }
703  // raise each index by one
704  for (i=1;i<=size(T);i++)
705  {
706    for (j=1;j<=size(T[i]);j++)
707    {
708      T[i][j]=T[i][j]+1;
709    }
710  }
711  return(T);
712}
713example
714{
715   "EXAMPLE:";
716   echo=2;
717   // the lattice points of the unit square in the plane
718   list polygon=intvec(0,0),intvec(0,1),intvec(1,0),intvec(1,1);
719   // the triangulations of this lattice point configuration are computed
720   list triang=triangulations(polygon);
721   triang;
722}
723
724/////////////////////////////////////////////////////////////////////////////
725
726proc secondaryPolytope (list polygon,list #)
727"USAGE:  secondaryPolytope(polygon[,#]); list polygon, list #
728ASSUME:  - polygon is a list of integer vectors of the same size representing
729           the affine coordinates of lattice points
730@*       - if the triangulations of the corresponding polygon have already been
731           computed with the procedure triangulations then these can be given as
732           a second (optional) argument in order to avoid doing this computation
733           again
734PURPOSE: the procedure considers the marked polytope given as the convex hull of
735         the lattice points and with these lattice points as markings; it then
736         computes the lattice points of the secondary polytope given by this
737         marked polytope which correspond to the triangulations computed by
738         the procedure triangulations
739RETURN:  list, say L, such that:
740@*             L[1] = intmat, each row gives the affine coordinates of a lattice
741                      point in the secondary polytope given by the marked
742                      polytope corresponding to polygon
743@*             L[2] = the list of corresponding triangulations
744NOTE: if the triangluations are not handed over as optional argument the
745      procedure calls for its computation of these triangulations the program
746      points2triangs from the program topcom by Joerg Rambau, Universitaet
747      Bayreuth; it therefore is necessary that this program is installed in
748      order to use this procedure; see
749@*    http://www.rambau.wm.uni-bayreuth.de/TOPCOM/);
750EXAMPLE: example secondaryPolytope;   shows an example"
751{
752  // compute the triangulations of the point configuration with points2triangs
753  if (size(#)==0)
754  {
755    list triangs=triangulations(polygon);
756  }
757  else
758  {
759    list triangs=#;
760  }
761  int i,j,k,l;
762  intmat N[2][2]; // is used to compute areas of triangles
763  intvec vertex;  // stores a point in the secondary polytope as
764                  // intermediate result
765  int eintrag;
766  int halt;
767  intmat secpoly[size(triangs)][size(polygon)];   // stores all lattice points
768                                                  // of the secondary polytope
769  // consider each triangulation and compute the corresponding point
770  // in the secondary polytope
771  for (i=1;i<=size(triangs);i++)
772  {
773    // for each triangulation we have to compute the coordinates
774    // corresponding to each marked point
775    for (j=1;j<=size(polygon);j++)
776    {
777      eintrag=0;
778      // for each marked point we have to consider all triangles in the
779      // triangulation which involve this particular point
780      for (k=1;k<=size(triangs[i]);k++)
781      {
782        halt=0;
783        for (l=1;(l<=3) and (halt==0);l++)
784        {
785          if (triangs[i][k][l]==j)
786          {
787            halt=1;
788            N[1,1]=polygon[triangs[i][k][3]][1]-polygon[triangs[i][k][1]][1];
789            N[1,2]=polygon[triangs[i][k][2]][1]-polygon[triangs[i][k][1]][1];
790            N[2,1]=polygon[triangs[i][k][3]][2]-polygon[triangs[i][k][1]][2];
791            N[2,2]=polygon[triangs[i][k][2]][2]-polygon[triangs[i][k][1]][2];
792            eintrag=eintrag+abs(det(N));
793          }
794        }
795      }
796      vertex[j]=eintrag;
797    }
798    secpoly[i,1..size(polygon)]=vertex;
799  }
800  return(list(secpoly,triangs));
801}
802example
803{
804   "EXAMPLE:";
805   echo=2;
806   // the lattice points of the unit square in the plane
807   list polygon=intvec(0,0),intvec(0,1),intvec(1,0),intvec(1,1);
808   // the secondary polytope of this lattice point configuration is computed
809   list secpoly=secondaryPolytope(polygon);
810   // the points in the secondary polytope
811   print(secpoly[1]);
812   // the corresponding triangulations
813   secpoly[2];
814}
815
816///////////////////////////////////////////////////////////////////////////////
817/// PROCEDURES USING POLYMAKE AND TOPCOM
818///////////////////////////////////////////////////////////////////////////////
819
820proc secondaryFan (list polygon,list #)
821"USAGE:  secondaryFan(polygon[,#]); list polygon, list #
822ASSUME:  - polygon is a list of integer vectors of the same size representing
823           the affine coordinates of lattice points
824@*       - if the triangulations of the corresponding polygon have already been
825           computed with the procedure triangulations then these can be given
826           as a second (optional) argument in order to avoid doing this
827           computation again
828PURPOSE: the procedure considers the marked polytope given as the convex hull of
829         the lattice points and with these lattice points as markings; it then
830         computes the lattice points of the secondary polytope given by this
831         marked polytope which correspond to the triangulations computed by
832         the procedure triangulations
833RETURN:  list, the ith entry of L[1] contains information about the ith cone in
834               the secondary fan of the polygon, i.e. the cone dual to the
835               ith vertex of the secondary polytope
836@*             L[1][i][1] = integer matrix representing the inequalities which
837                            describe the cone dual to the ith vertex
838@*             L[1][i][2] = a list which contains the inequalities represented
839                            by L[1][i][1] as a list of strings, where we use the
840                            variables x(1),...,x(n)
841@*             L[1][i][3] = only present if 'er' is set to 1; in that case it is
842                            an interger matrix whose rows are the extreme rays
843                            of the cone
844@*             L[2] = is an integer matrix whose rows span the linearity space
845                      of the fan, i.e. the linear space which is contained in
846                      each cone
847@*             L[3] = the secondary polytope in the format of the procedure
848                      polymakePolytope
849@*             L[4] = the list of triangulations corresponding to the vertices
850                      of the secondary polytope
851NOTE:- the procedure calls for its computation polymake by Ewgenij Gawrilow,
852       TU Berlin and Michael Joswig, so it only works if polymake is installed;
853       see http://www.polymake.org/
854@*   - in the optional argument # it is possible to hand over other names for
855       the variables to be used -- be careful, the format must be correct and
856       that is not tested, e.g. if you want the variable names to be
857       u00,u10,u01,u11 then you must hand over the string 'u11,u10,u01,u11'
858@*   - if the triangluations are not handed over as optional argument the
859       procedure calls for its computation of these triangulations the program
860       points2triangs from the program topcom by Joerg Rambau, Universitaet
861       Bayreuth; it therefore is necessary that this program is installed in
862       order to use this procedure; see
863@*     http://www.rambau.wm.uni-bayreuth.de/TOPCOM/);
864EXAMPLE: example secondaryFan;   shows an example"
865{
866  if (size(#)==0)
867  {
868    list triang=triangulations(polygon);
869  }
870  else
871  {
872    list triang=#[1];
873  }
874  list sp=secondaryPolytope(polygon,triang);
875  list spp=polymakePolytope(sp[1]);
876  list sf=normalFanL(spp[1],spp[4],spp[3],1);
877  return(list(sf[1],sf[2],spp,triang));
878}
879example
880{
881   "EXAMPLE:";
882   echo=2;
883   // the lattice points of the unit square in the plane
884   list polygon=intvec(0,0),intvec(0,1),intvec(1,0),intvec(1,1);
885   // the secondary polytope of this lattice point configuration is computed
886   list secfan=secondaryFan(polygon);
887   // the number of cones in the secondary fan of the polygon
888   size(secfan[1]);
889   // the inequalities of the first cone as matrix are:
890   print(secfan[1][1][1]);
891   // the inequalities of the first cone as string are:
892   print(secfan[1][1][2]);
893   // the rows of the following matrix are the extreme rays of the first cone:
894   print(secfan[1][1][3]);
895   // each cone contains the linearity space spanned by:
896   print(secfan[2]);
897   // the points in the secondary polytope
898   print(secfan[3][1]);
899   // the corresponding triangulations
900   secfan[4];
901}
902
903
904////////////////////////////////////////////////////////////////////////////////
905/// PROCEDURES CONCERNED WITH PLANAR POLYGONS
906////////////////////////////////////////////////////////////////////////////////
907
908proc cycleLength (list boundary,intvec interior)
909"USAGE:  cycleLength(boundary,interior); list boundary, intvec interior
910ASSUME:  boundary is a list of integer vectors describing a cycle in some
911         convex lattice polygon around the lattice point interior ordered
912         clock wise
913RETURN:  string, the cycle length of the corresponding cycle in the dual
914                 tropical curve
915EXAMPLE: example cycleLength;   shows an example"
916{
917  int j;
918  // create a ring whose variables are indexed by the points in
919  // boundary resp. by interior
920  string rst="ring cyclering=0,(u"+string(interior[1])+string(interior[2]);
921  for (j=1;j<=size(boundary);j++)
922  {
923    rst=rst+",u"+string(boundary[j][1])+string(boundary[j][2]);
924  }
925  rst=rst+"),lp;";
926  execute(rst);
927  // add the first and second point at the end of boundary
928  boundary[size(boundary)+1]=boundary[1];
929  boundary[size(boundary)+1]=boundary[2];
930  poly cl,summand; // takes the cycle length
931  matrix N1[2][2]; // used to compute the area of a triangle
932  matrix N2[2][2]; // used to compute the area of a triangle
933  matrix N3[2][2]; // used to compute the area of a triangle
934  // for each original point in boundary compute its contribution to the cycle
935  for (j=2;j<=size(boundary)-1;j++)
936  {
937    N1=boundary[j-1]-interior,boundary[j]-interior;
938    N2=boundary[j]-interior,boundary[j+1]-interior;
939    N3=boundary[j+1]-interior,boundary[j-1]-interior;
940    execute("summand=-u"+string(boundary[j][1])+string(boundary[j][2])+"+u"+string(interior[1])+string(interior[2])+";");
941    summand=summand*(det(N1)+det(N2)+det(N3))/(det(N1)*det(N2));
942    cl=cl+summand;
943  }
944  return(string(cl));
945}
946example
947{
948   "EXAMPLE:";
949   echo=2;
950   // the integer vectors in boundary are lattice points on the boundary
951   // of a convex lattice polygon in the plane
952   list boundary=intvec(0,0),intvec(0,1),intvec(0,2),intvec(2,2),
953                 intvec(2,1),intvec(2,0);
954   // interior is a lattice point in the interior of this lattice polygon
955   intvec interior=1,1;
956   // compute the general cycle length of a cycle of the corresponding cycle
957   // in the dual tropical curve, note that (0,1) and (2,1) do not contribute
958   cycleLength(boundary,interior);
959}
960
961/////////////////////////////////////////////////////////////////////////////
962
963proc splitPolygon (list markings)
964"USAGE:  splitPolygon (markings);  markings list
965ASSUME:  markings is a list of integer vectors representing lattice points in
966         the plane which we consider as the marked points of the convex lattice
967         polytope spanned by them
968PURPOSE: split the marked points in the vertices, the points on the facets
969         which are not vertices, and the interior points
970RETURN:  list, L consisting of three lists
971@*             L[1]    : represents the vertices the polygon ordered clockwise
972@*                       L[1][i][1] = intvec, the coordinates of the ith vertex
973@*                       L[1][i][2] = int, the position of L[1][i][1] in markings
974@*             L[2][i] : represents the lattice points on the facet of the
975                         polygon with endpoints L[1][i] and L[1][i+1]
976                         (i considered modulo size(L[1]))
977@*                       L[2][i][j][1] = intvec, the coordinates of the jth
978                                                 lattice point on that facet
979@*                       L[2][i][j][2] = int, the position of L[2][i][j][1]
980                                              in markings
981@*             L[3]    : represents the interior lattice points of the polygon
982@*                       L[3][i][1] = intvec, coordinates of ith interior point
983@*                       L[3][i][2] = int, the position of L[3][i][1] in markings
984EXAMPLE: example splitPolygon;   shows an example"
985{
986  list vert; // stores the result
987  // compute the boundary of the polygon in an oriented way
988  list pb=findOrientedBoundary(markings);
989  // the vertices are just the second entry of pb
990  vert[1]=pb[2];
991  int i,j,k;      // indices
992  list boundary;  // stores the points on the facets of the
993                  // polygon which are not vertices
994  // append to the boundary points as well as to the vertices
995  // the first vertex a second time
996  pb[1]=pb[1]+list(pb[1][1]);
997  pb[2]=pb[2]+list(pb[2][1]);
998  // for each vertex find all points on the facet of the polygon with this vertex
999  // and the next vertex as endpoints
1000  int z=2;
1001  for (i=1;i<=size(vert[1]);i++)
1002  {
1003    j=1;
1004    list facet; // stores the points on this facet which are not vertices
1005    // while the next vertex is not reached, store the boundary lattice point
1006    while (pb[1][z]!=pb[2][i+1])
1007    {
1008      facet[j]=pb[1][z];
1009      j++;
1010      z++;
1011    }
1012    // store the points on the ith facet as boundary[i]
1013    boundary[i]=facet;
1014    kill facet;
1015    z++;
1016  }
1017  // store the information on the boundary in vert[2]
1018  vert[2]=boundary;
1019  // find the remaining points in the input which are not on
1020  // the boundary by checking
1021  // for each point in markings if it is contained in pb[1]
1022  list interior=markings;
1023  for (i=size(interior);i>=1;i--)
1024  {
1025    for (j=1;j<=size(pb[1])-1;j++)
1026    {
1027      if (interior[i]==pb[1][j])
1028      {
1029        interior=delete(interior,i);
1030        j=size(pb[1]);
1031      }
1032    }
1033  }
1034  // store the interior points in vert[3]
1035  vert[3]=interior;
1036  // add to each point in vert the index which it gets from
1037  // its position in the input markings;
1038  // do so for ver[1]
1039  for (i=1;i<=size(vert[1]);i++)
1040  {
1041    j=1;
1042    while (markings[j]!=vert[1][i])
1043    {
1044      j++;
1045    }
1046    vert[1][i]=list(vert[1][i],j);
1047  }
1048  // do so for ver[2]
1049  for (i=1;i<=size(vert[2]);i++)
1050  {
1051    for (k=1;k<=size(vert[2][i]);k++)
1052    {
1053      j=1;
1054      while (markings[j]!=vert[2][i][k])
1055      {
1056        j++;
1057      }
1058      vert[2][i][k]=list(vert[2][i][k],j);
1059    }
1060  }
1061  // do so for ver[3]
1062  for (i=1;i<=size(vert[3]);i++)
1063  {
1064    j=1;
1065    while (markings[j]!=vert[3][i])
1066    {
1067      j++;
1068    }
1069    vert[3][i]=list(vert[3][i],j);
1070  }
1071  return(vert);
1072}
1073example
1074{
1075   "EXAMPLE:";
1076   echo=2;
1077   // the lattice polygon spanned by the points (0,0), (3,0) and (0,3)
1078   // with all integer points as markings
1079   list polygon=intvec(1,1),intvec(3,0),intvec(2,0),intvec(1,0),
1080                intvec(0,0),intvec(2,1),intvec(0,1),intvec(1,2),
1081                intvec(0,2),intvec(0,3);
1082   // split the polygon in its vertices, its facets and its interior points
1083   list sp=splitPolygon(polygon);
1084   // the vertices
1085   sp[1];
1086   // the points on facets which are not vertices
1087   sp[2];
1088   // the interior points
1089   sp[3];
1090}
1091
1092
1093/////////////////////////////////////////////////////////////////////////////
1094
1095proc eta (list triang,list polygon)
1096"USAGE:  eta(triang,polygon);  triang, polygon list
1097ASSUME:  polygon has the format of the output of splitPolygon, i.e. it is a
1098         list with three entries describing a convex lattice polygon in the
1099         following way:
1100@*       polygon[1] : is a list of lists; for each i the entry polygon[1][i][1]
1101                      is a lattice point which is a vertex of the lattice
1102                      polygon, and polygon[1][i][2] is an integer assigned to
1103                      this lattice point as identifying index
1104@*       polygon[2] : is a list of lists; for each vertex of the polygon,
1105                      i.e. for each entry in polygon[1], it contains a list
1106                      polygon[2][i], which contains the lattice points on the
1107                      facet with endpoints polygon[1][i] and polygon[1][i+1]
1108                      - i considered mod size(polygon[1]);
1109                      each such lattice point contributes an entry
1110                      polygon[2][i][j][1] which is an integer
1111                      vector giving the coordinate of the lattice point and an
1112                      entry polygon[2][i][j][2] which is the identifying index
1113@*       polygon[3] : is a list of lists, where each entry corresponds to a
1114                      lattice point in the interior of the polygon, with
1115                      polygon[3][j][1] being the coordinates of the point
1116                      and polygon[3][j][2] being the identifying index;
1117@*       triang is a list of integer vectors all of size three describing a
1118         triangulation of the polygon described by polygon; if an entry of
1119         triang is the vector (i,j,k) then the triangle is built by the vertices
1120         with indices i, j and k
1121RETURN:  intvec, the integer vector eta describing that vertex of the Newton
1122                 polytope discriminant of the polygone whose dual cone in the
1123                 Groebner fan contains the cone of the secondary fan of the
1124                 polygon corresponding to the given triangulation
1125NOTE:  for a better description of eta see Gelfand, Kapranov,
1126       Zelevinski: Discriminants, Resultants and multidimensional Determinants.
1127       Chapter 10.
1128EXAMPLE: example eta;   shows an example"
1129{
1130  int i,j,k,l,m,n; // index variables
1131  list ordpolygon;   // stores the lattice points in the order
1132                     // used in the triangulation
1133  list triangarea; // stores the areas of the triangulations
1134  intmat N[2][2];  // used to compute triangle areas
1135  // 1) store the lattice points in the order used in the triangulation
1136  // go first through all vertices of the polytope
1137  for (j=1;j<=size(polygon[1]);j++)
1138  {
1139    ordpolygon[polygon[1][j][2]]=polygon[1][j][1];
1140  }
1141  // then consider all inner points
1142  for (j=1;j<=size(polygon[3]);j++)
1143  {
1144    ordpolygon[polygon[3][j][2]]=polygon[3][j][1];
1145  }
1146  // finally consider all lattice points on the boundary which are not vertices
1147  for (j=1;j<=size(polygon[2]);j++)
1148  {
1149    for (i=1;i<=size(polygon[2][j]);i++)
1150    {
1151      ordpolygon[polygon[2][j][i][2]]=polygon[2][j][i][1];
1152    }
1153  }
1154  // 2) compute for each triangle in the triangulation the area of the triangle
1155  for (i=1;i<=size(triang);i++)
1156  {
1157    // Note that the ith lattice point in orderedpolygon has the
1158    // number i-1 in the triangulation!
1159    N=ordpolygon[triang[i][1]]-ordpolygon[triang[i][2]],ordpolygon[triang[i][1]]-ordpolygon[triang[i][3]];
1160    triangarea[i]=abs(det(N));
1161  }
1162  intvec ETA;        // stores the eta_ij
1163  int etaij;         // stores the part of eta_ij during computations
1164                     // which comes from triangle areas
1165  int seitenlaenge;  // stores the part of eta_ij during computations
1166                     // which comes from boundary facets
1167  list seiten;       // stores the lattice points on facets of the polygon
1168  intvec v;          // used to compute a facet length
1169  // 3) store first in seiten[i] all lattice points on the facet
1170  //    connecting the ith vertex,
1171  //    i.e. polygon[1][i], with the i+1st vertex, i.e. polygon[1][i+1],
1172  //    where we replace i+1
1173  //    1 if i=size(polygon[1]);
1174  //    then append the last entry of seiten once more at the very
1175  //    beginning of seiten, so
1176  //    that the index is shifted by one
1177  for (i=1;i<=size(polygon[1]);i++)
1178  {
1179    if (i<size(polygon[1]))
1180    {
1181      seiten[i]=list(polygon[1][i])+polygon[2][i]+list(polygon[1][i+1]);
1182    }
1183    else
1184    {
1185      seiten[i]=list(polygon[1][i])+polygon[2][i]+list(polygon[1][1]);
1186    }
1187  }
1188  seiten=insert(seiten,seiten[size(seiten)],0);
1189  // 4) compute the eta_ij for all vertices of the polygon
1190  for (j=1;j<=size(polygon[1]);j++)
1191  {
1192    // the vertex itself contributes a 1
1193    etaij=1;
1194    // check for each triangle in the triangulation ...
1195    for (k=1;k<=size(triang);k++)
1196    {
1197      // ... if the vertex is actually a vertex of the triangle ...
1198      if ((polygon[1][j][2]==triang[k][1]) or (polygon[1][j][2]==triang[k][2]) or (polygon[1][j][2]==triang[k][3]))
1199      {
1200        // ... if so, add the area of the triangle to etaij
1201        etaij=etaij+triangarea[k];
1202        // then check if that triangle has a facet which is contained
1203        // in one of the
1204        // two facets of the polygon which are adjecent to the given vertex ...
1205        // these two facets are seiten[j] and seiten[j+1]
1206        for (n=j;n<=j+1;n++)
1207        {
1208          // check for each lattice point in the facet of the polygon ...
1209          for (l=1;l<=size(seiten[n]);l++)
1210          {
1211            // ... and for each lattice point in the triangle ...
1212            for (m=1;m<=size(triang[k]);m++)
1213            {
1214              // ... if they coincide and are not the vertex itself ...
1215              if ((seiten[n][l][2]==triang[k][m]) and (seiten[n][l][2]!=polygon[1][j][2]))
1216              {
1217                // if so, then compute the vector pointing from this
1218                // lattice point to the vertex
1219                v=polygon[1][j][1]-seiten[n][l][1];
1220                // and the lattice length of this vector has to be
1221                // subtracted from etaij
1222                etaij=etaij-abs(gcd(v[1],v[2]));
1223              }
1224            }
1225          }
1226        }
1227      }
1228    }
1229    // store etaij in the list
1230    ETA[polygon[1][j][2]]=etaij;
1231  }
1232  // 5) compute the eta_ij for all lattice points on the facets
1233  //    of the polygon which are not vertices, these are the
1234  //    lattice points in polygon[2][1] to polygon[2][size(polygon[1])]
1235  for (i=1;i<=size(polygon[2]);i++)
1236  {
1237    for (j=1;j<=size(polygon[2][i]);j++)
1238    {
1239      // initialise etaij
1240      etaij=0;
1241      // initialise seitenlaenge
1242      seitenlaenge=0;
1243      // check for each triangle in the triangulation ...
1244      for (k=1;k<=size(triang);k++)
1245      {
1246        // ... if the vertex is actually a vertex of the triangle ...
1247        if ((polygon[2][i][j][2]==triang[k][1]) or (polygon[2][i][j][2]==triang[k][2]) or (polygon[2][i][j][2]==triang[k][3]))
1248        {
1249          // ... if so, add the area of the triangle to etaij
1250          etaij=etaij+triangarea[k];
1251          // then check if that triangle has a facet which is contained in the
1252          // facet of the polygon which contains the lattice point in question,
1253          // this is the facet seiten[i+1];
1254          // check for each lattice point in the facet of the polygon ...
1255          for (l=1;l<=size(seiten[i+1]);l++)
1256          {
1257            // ... and for each lattice point in the triangle ...
1258            for (m=1;m<=size(triang[k]);m++)
1259            {
1260              // ... if they coincide and are not the vertex itself ...
1261              if ((seiten[i+1][l][2]==triang[k][m]) and (seiten[i+1][l][2]!=polygon[2][i][j][2]))
1262              {
1263                // if so, then compute the vector pointing from
1264                // this lattice point to the vertex
1265                v=polygon[2][i][j][1]-seiten[i+1][l][1];
1266                // and the lattice length of this vector contributes
1267                // to seitenlaenge
1268                seitenlaenge=seitenlaenge+abs(gcd(v[1],v[2]));
1269              }
1270            }
1271          }
1272        }
1273      }
1274      // if the lattice point was a vertex of any triangle
1275      // in the triangulation ...
1276      if (etaij!=0)
1277      {
1278        // then eta_ij is the sum of the triangle areas minus seitenlaenge
1279        ETA[polygon[2][i][j][2]]=etaij-seitenlaenge;
1280      }
1281      else
1282      {
1283        // otherwise it is just zero
1284        ETA[polygon[2][i][j][2]]=0;
1285      }
1286    }
1287  }
1288  // 4) compute the eta_ij for all inner lattice points of the polygon
1289  for (j=1;j<=size(polygon[3]);j++)
1290  {
1291    // initialise etaij
1292    etaij=0;
1293    // check for each triangle in the triangulation ...
1294    for (k=1;k<=size(triang);k++)
1295    {
1296      // ... if the vertex is actually a vertex of the triangle ...
1297      if ((polygon[3][j][2]==triang[k][1]) or (polygon[3][j][2]==triang[k][2]) or (polygon[3][j][2]==triang[k][3]))
1298      {
1299        // ... if so, add the area of the triangle to etaij
1300        etaij=etaij+triangarea[k];
1301      }
1302    }
1303    // store etaij in ETA
1304    ETA[polygon[3][j][2]]=etaij;
1305  }
1306  return(ETA);
1307}
1308example
1309{
1310   "EXAMPLE:";
1311   echo=2;
1312   // the lattice polygon spanned by the points (0,0), (3,0) and (0,3)
1313   // with all integer points as markings
1314   list polygon=intvec(1,1),intvec(3,0),intvec(2,0),intvec(1,0),
1315                intvec(0,0),intvec(2,1),intvec(0,1),intvec(1,2),
1316                intvec(0,2),intvec(0,3);
1317   // split the polygon in its vertices, its facets and its interior points
1318   list sp=splitPolygon(polygon);
1319   // define a triangulation by connecting the only interior point
1320   //        with the vertices
1321   list triang=intvec(1,2,5),intvec(1,5,10),intvec(1,5,10);
1322   // compute the eta-vector of this triangulation
1323   eta(triang,sp);
1324}
1325
1326/////////////////////////////////////////////////////////////////////////////
1327
1328proc findOrientedBoundary (list polygon)
1329"USAGE: findOrientedBoundary(polygon); polygon list
1330ASSUME: polygon is a list of integer vectors defining integer lattice points
1331        in the plane
1332RETURN: list l with the following interpretation
1333@*            l[1] = list of integer vectors such that the polygonal path
1334                     defined by these is the boundary of the convex hull of
1335                     the lattice points in polygon
1336@*            l[2] = list, the redundant points in l[1] have been removed
1337EXAMPLE:     example findOrientedBoundary;   shows an example"
1338{
1339  // Order the vertices such that passing from one to the next we travel along
1340  // the boundary of the convex hull of the vertices clock wise
1341  int d,k,i,j;
1342  intmat D[2][2];
1343  /////////////////////////////////////
1344  // Treat first the pathological cases that the polygon is not two-dimensional:
1345  /////////////////////////////////////
1346  // if the polygon is empty or only one point or a line segment of two points
1347  if (size(polygon)<=2)
1348  {
1349    return(list(polygon,polygon));
1350  }
1351  // check is the polygon is only a line segment given by more than two points;
1352  // for this first compute sum of the absolute values of the determinants
1353  // of the matrices whose
1354  // rows are the vectors pointing from the first to the second point
1355  // and from the
1356  // the first point to the ith point for i=3,...,size(polygon);
1357  // if this sum is zero
1358  // then the polygon is a line segment and we have to find its end points
1359  d=0;
1360  for (i=3;i<=size(polygon);i++)
1361  {
1362    D=polygon[2]-polygon[1],polygon[i]-polygon[1];
1363    d=d+abs(det(D));
1364  }
1365  if (d==0) // then polygon is a line segment
1366  {
1367    intmat laenge[size(polygon)][size(polygon)];
1368    intvec mp;
1369    //   for this collect first all vectors pointing from one lattice
1370    //   point to the next,
1371    //   compute their pairwise angles and their lengths
1372    for (i=1;i<=size(polygon)-1;i++)
1373    {
1374      for (j=i+1;j<=size(polygon);j++)
1375      {
1376        mp=polygon[i]-polygon[j];
1377        laenge[i,j]=abs(gcd(mp[1],mp[2]));
1378      }
1379    }
1380    mp=maxPosInIntmat(laenge);
1381    list endpoints=polygon[mp[1]],polygon[mp[2]];
1382    intvec abstand;
1383    for (i=1;i<=size(polygon);i++)
1384    {
1385      abstand[i]=0;
1386      if (i<mp[1])
1387      {
1388        abstand[i]=laenge[i,mp[1]];
1389      }
1390      if (i>mp[1])
1391      {
1392        abstand[i]=laenge[mp[1],i];
1393      }
1394    }
1395    polygon=sortlistbyintvec(polygon,abstand);
1396    return(list(polygon,endpoints));
1397  }
1398  ///////////////////////////////////////////////////////////////
1399  list orderedvertices;  // stores the vertices in an ordered way
1400  list minimisedorderedvertices;  // stores the vertices in an ordered way;
1401                                  // redundant ones removed
1402  list comparevertices; // stores vertices which should be compared to
1403                        // the testvertex
1404  orderedvertices[1]=polygon[1]; // set the starting vertex
1405  minimisedorderedvertices[1]=polygon[1]; // set the starting vertex
1406  intvec testvertex=polygon[1];  //vertex to which the others have to be compared
1407  intvec startvertex=polygon[1]; // keep the starting vertex to test,
1408                                 // when the end is reached
1409  int endtest;                   // is set to one, when the end is reached
1410  int startvertexfound;// is 1, once for some testvertex a candidate
1411                       // for the next vertex has been found
1412  polygon=delete(polygon,1);    // delete the testvertex
1413  intvec v,w;
1414  int l=1;  // counts the vertices
1415  // the basic idea is that a vertex can be
1416  // the next one on the boundary if all other vertices
1417  // lie to the right of the vector v pointing
1418  // from the testvertex to this one; this can be tested
1419  // by checking if the determinant of the 2x2-matrix
1420  // with first column v and second column the vector w,
1421  // pointing from the testvertex to the new vertex,
1422  // is non-positive; if this is the case for all
1423  // new vertices, then the one in consideration is
1424  // a possible choice for the next vertex on the boundary
1425  // and it is stored in naechste; we can then order
1426  // the candidates according to their distance from
1427  // the testvertex; then they occur on the boundary in that order!
1428  while (endtest==0)
1429  {
1430    list naechste;  // stores the possible choices for the next vertex
1431    k=1;
1432    for (i=1;i<=size(polygon);i++)
1433    {
1434      d=0;  // stores the value of the determinant of (v,w)
1435      v=polygon[i]-testvertex; // points from the testvertex to the ith vertex
1436      comparevertices=delete(polygon,i); // we needn't compare v to itself
1437      // we should compare v to the startvertex-testvertex;
1438      // in the first calling of the loop
1439      // this is irrelevant since the difference will be zero;
1440      // however, later on it will
1441      // be vital, since we delete the vertices
1442      // which we have already tested from the list
1443      // of all vertices, and when all vertices
1444      // on the boundary have been found we would
1445      // therefore find a vertex in the interior
1446      // as candidate; but always testing against
1447      // the starting vertex, this cannot happen
1448      comparevertices[size(comparevertices)+1]=startvertex;
1449      for (j=1;(j<=size(comparevertices)) and (d<=0);j++)
1450      {
1451        w=comparevertices[j]-testvertex; // points form the testvertex
1452                                         // to the jth vertex
1453        D=v,w;
1454        d=det(D);
1455      }
1456      if (d<=0) // if all determinants are non-positive,
1457      { // then the ith vertex is a candidate
1458        naechste[k]=list(polygon[i],i,scalarproduct(v,v));// we store the vertex,
1459                                                          //its position, and its
1460        k++; // distance from the testvertex
1461      }
1462    }
1463    if (size(naechste)>0) // then a candidate for the next vertex has been found
1464    {
1465      startvertexfound=1; // at least once a candidate has been found
1466      naechste=sortlist(naechste,3);  // we order the candidates according
1467                                      // to their distance from testvertex;
1468      for (j=1;j<=size(naechste);j++) // then we store them in this
1469      { // order in orderedvertices
1470        l++;
1471        orderedvertices[l]=naechste[j][1];
1472      }
1473      testvertex=naechste[size(naechste)][1];  // we store the last one as
1474                                               // next testvertex;
1475      // store the next corner of NSD
1476      minimisedorderedvertices[size(minimisedorderedvertices)+1]=testvertex;
1477      naechste=sortlist(naechste,2); // then we reorder the vertices
1478                                     // according to their position
1479      for (j=size(naechste);j>=1;j--) // and we delete them from the vertices
1480      {
1481        polygon=delete(polygon,naechste[j][2]);
1482      }
1483    }
1484    else // that means either that the vertex was inside the polygon,
1485    {    // or that we have reached the last vertex on the boundary
1486         // of the polytope
1487      if (startvertexfound==0) // the vertex was in the interior;
1488      { // we delete it and start all over again
1489        orderedvertices[1]=polygon[1];
1490        minimisedorderedvertices[1]=polygon[1];
1491        testvertex=polygon[1];
1492        startvertex=polygon[1];
1493        polygon=delete(polygon,1);
1494      }
1495      else // we have reached the last vertex on the boundary of
1496      { // the polytope and can stop
1497        endtest=1;
1498      }
1499    }
1500    kill naechste;
1501  }
1502  // test if the first vertex in minimisedorderedvertices
1503  // is on the same line with the second and
1504  // the last, i.e. if we started our search in the
1505  // middle of a face; if so, delete it
1506  v=minimisedorderedvertices[2]-minimisedorderedvertices[1];
1507  w=minimisedorderedvertices[size(minimisedorderedvertices)]-minimisedorderedvertices[1];
1508  D=v,w;
1509  if (det(D)==0)
1510  {
1511    minimisedorderedvertices=delete(minimisedorderedvertices,1);
1512  }
1513  // test if the first vertex in minimisedorderedvertices
1514  // is on the same line with the two
1515  // last ones, i.e. if we started our search at the end of a face;
1516  // if so, delete it
1517  v=minimisedorderedvertices[size(minimisedorderedvertices)-1]-minimisedorderedvertices[1];
1518  w=minimisedorderedvertices[size(minimisedorderedvertices)]-minimisedorderedvertices[1];
1519  D=v,w;
1520  if (det(D)==0)
1521  {
1522    minimisedorderedvertices=delete(minimisedorderedvertices,size(minimisedorderedvertices));
1523  }
1524  return(list(orderedvertices,minimisedorderedvertices));
1525}
1526example
1527{
1528   "EXAMPLE:";
1529   echo=2;
1530// the following lattice points in the plane define a polygon
1531   list polygon=intvec(0,0),intvec(3,1),intvec(1,0),intvec(2,0),
1532                intvec(1,1),intvec(3,2),intvec(1,2),intvec(2,3),
1533                intvec(2,4);
1534// we compute its boundary
1535   list boundarypolygon=findOrientedBoundary(polygon);
1536// the points on the boundary ordered clockwise are boundarypolygon[1]
1537   boundarypolygon[1];
1538// the vertices of the boundary are boundarypolygon[2]
1539   boundarypolygon[2];
1540}
1541
1542
1543/////////////////////////////////////////////////////////////////////////////
1544
1545proc cyclePoints (list triang,list points,int pt)
1546"USAGE:      cyclePoints(triang,points,pt)  triang,points list, pt int
1547ASSUME:      - points is a list of integer vectors describing the lattice
1548               points of a marked polygon;
1549@*           - triang is a list of integer vectors describing a triangulation
1550               of the marked polygon in the sense that an integer vector of
1551               the form (i,j,k) describes the triangle formed by polygon[i],
1552               polygon[j] and polygon[k];
1553@*           - pt is an integer between 1 and size(points), singling out a
1554               lattice point among the marked points
1555PURPOSE:     consider the convex lattice polygon, say P, spanned by all lattice
1556             points in points which in the triangulation triang are connected
1557             to the point points[pt]; the procedure computes all marked points
1558             in points which lie on the boundary of that polygon, ordered
1559             clockwise
1560RETURN:      list, of integer vectors which are the coordinates of the lattice
1561                   points on the boundary of the above mentioned polygon P, if
1562                   this polygon is not the empty set (that would be the case if
1563                   points[pt] is not a vertex of any triangle in the
1564                   triangulation); otherwise return the empty list
1565EXAMPLE:     example cyclePoints;   shows an example"
1566{
1567  int i,j; // indices
1568  list v;  // saves the indices of lattice points connected to the
1569           // interior point in the triangulation
1570  // save all points in triangulations containing pt in v
1571  for (i=1;i<=size(triang);i++)
1572  {
1573    if ((triang[i][1]==pt) or (triang[i][2]==pt) or (triang[i][3]==pt))
1574    {
1575      j++;
1576      v[3*j-2]=triang[i][1];
1577      v[3*j-1]=triang[i][2];
1578      v[3*j]=triang[i][3];
1579    }
1580  }
1581  if (size(v)==0)
1582  {
1583    return(list());
1584  }
1585  // remove pt itself and redundancies in v
1586  for (i=size(v);i>=1;i--)
1587  {
1588    j=1;
1589    while ((j<i) and (v[i]!=v[j]))
1590    {
1591      j++;
1592    }
1593    if ((j<i) or (v[i]==pt))
1594    {
1595      v=delete(v,i);
1596    }
1597  }
1598  // save in pts the coordinates of the points with indices in v
1599  list pts;
1600  for (i=1;i<=size(v);i++)
1601  {
1602    pts[i]=points[v[i]];
1603  }
1604  // consider the convex polytope spanned by the points in pts,
1605  // find the points on the
1606  // boundary and order them clockwise
1607  return(findOrientedBoundary(pts)[1]);
1608}
1609example
1610{
1611   "EXAMPLE:";
1612   echo=2;
1613   // the lattice polygon spanned by the points (0,0), (3,0) and (0,3)
1614   // with all integer points as markings
1615   list points=intvec(1,1),intvec(3,0),intvec(2,0),intvec(1,0),
1616               intvec(0,0),intvec(2,1),intvec(0,1),intvec(1,2),
1617               intvec(0,2),intvec(0,3);
1618   // define a triangulation
1619   list triang=intvec(1,2,5),intvec(1,5,7),intvec(1,7,9),intvec(8,9,10),
1620               intvec(1,8,9),intvec(1,2,8);
1621   // compute the points connected to (1,1) in triang
1622   cyclePoints(triang,points,1);
1623}
1624
1625/////////////////////////////////////////////////////////////////////////////
1626
1627proc latticeArea (list polygon)
1628"USAGE:  latticeArea(polygon);   polygon list
1629ASSUME:  polygon is a list of integer vectors in the plane
1630RETURN:  int, the lattice area of the convex hull of the lattice points in
1631              polygon, i.e. twice the Euclidean area
1632EXAMPLE: example polygonlatticeArea;   shows an example"
1633{
1634  list pg=findOrientedBoundary(polygon)[2];
1635  int area;
1636  intmat M[2][2];
1637  for (int i=2;i<=size(pg)-1;i++)
1638  {
1639    M[1,1..2]=pg[i]-pg[1];
1640    M[2,1..2]=pg[i+1]-pg[1];
1641    area=area+abs(det(M));
1642  }
1643  return(area);
1644}
1645example
1646{
1647   "EXAMPLE:";
1648   echo=2;
1649   // define a polygon with lattice area 5
1650   list polygon=intvec(1,2),intvec(1,0),intvec(2,0),intvec(1,1),
1651                intvec(2,1),intvec(0,0);
1652   latticeArea(polygon);
1653}
1654
1655/////////////////////////////////////////////////////////////////////////////
1656
1657proc picksFormula (list polygon)
1658"USAGE:  picksFormula(polygon);   polygon list
1659ASSUME:  polygon is a list of integer vectors in the plane and consider their
1660         convex hull C
1661RETURN:  list, L of three integersthe
1662@*             L[1] : the lattice area of C, i.e. twice the Euclidean area
1663@*             L[2] : the number of lattice points on the boundary of C
1664@*             L[3] : the number of interior lattice points of C
1665NOTE: the integers in L are related by Pick's formula, namely: L[1]=L[2]+2*L[3]-2
1666EXAMPLE: example picksFormula;   shows an example"
1667{
1668  list pg=findOrientedBoundary(polygon)[2];
1669  int area,bdpts,i;
1670  intmat M[2][2];
1671  // compute the lattice area of the polygon, i.e. twice the Euclidean area
1672  for (i=2;i<=size(pg)-1;i++)
1673  {
1674    M[1,1..2]=pg[i]-pg[1];
1675    M[2,1..2]=pg[i+1]-pg[1];
1676    area=area+abs(det(M));
1677  }
1678  // compute the number of lattice points on the boundary
1679  intvec edge;
1680  pg[size(pg)+1]=pg[1];
1681  for (i=1;i<=size(pg)-1;i++)
1682  {
1683    edge=pg[i]-pg[i+1];
1684    bdpts=bdpts+abs(gcd(edge[1],edge[2]));
1685  }
1686  // Pick's formula says that the lattice area A, the number g of interior
1687  // points and
1688  // the number b of boundary points are connected by the formula: A=b+2g-2
1689  return(list(area,bdpts,(area-bdpts+2) div 2));
1690}
1691example
1692{
1693   "EXAMPLE:";
1694   echo=2;
1695   // define a polygon with lattice area 5
1696   list polygon=intvec(1,2),intvec(1,0),intvec(2,0),intvec(1,1),
1697                intvec(2,1),intvec(0,0);
1698   list pick=picksFormula(polygon);
1699   // the lattice area of the polygon is:
1700   pick[1];
1701   // the number of lattice points on the boundary is:
1702   pick[2];
1703   // the number of interior lattice points is:
1704   pick[3];
1705   // the number's are related by Pick's formula:
1706   pick[1]-pick[2]-2*pick[3]+2;
1707}
1708
1709/////////////////////////////////////////////////////////////////////////////
1710
1711proc ellipticNF (list polygon)
1712"USAGE:  ellipticNF(polygon);   polygon list
1713ASSUME:  polygon is a list of integer vectors in the plane such that their
1714         convex hull C has precisely one interior lattice point; i.e. C is the
1715         Newton polygon of an elliptic curve
1716PURPOSE: compute the normal form of the polygon with respect to the unimodular
1717         affine transformations T=A*x+v; there are sixteen different normal forms
1718         (see e.g. Bjorn Poonen, Fernando Rodriguez-Villegas: Lattice Polygons
1719                   and the number 12.  Amer. Math. Monthly  107  (2000),  no. 3,
1720                   238--250.)
1721RETURN:  list, L such that
1722@*             L[1] : list whose entries are the vertices of the normal form of
1723                      the polygon
1724@*             L[2] : the matrix A of the unimodular transformation
1725@*             L[3] : the translation vector v of the unimodular transformation
1726@*             L[4] : list such that the ith entry is the image of polygon[i]
1727                      under the unimodular transformation T
1728EXAMPLE: example ellipticNF;   shows an example"
1729{
1730  int i;            // index
1731  intvec edge;      // stores the vector of an edge
1732  intvec boundary;  // stores lattice lengths of the edges of the Newton cycle
1733  // find the vertices of the Newton cycle and order it clockwise
1734  list pg=findOrientedBoundary(polygon)[2];
1735  // check if there is precisely one interior point in the Newton polygon
1736  if (picksFormula(pg)[3]!=1)
1737  {
1738    ERROR("The polygon has not precisely one interior point!");
1739  }
1740  // insert the first vertex at the end once again
1741  pg[size(pg)+1]=pg[1];
1742  // compute the number of lattice points on each edge
1743  for (i=1;i<=size(pg)-1;i++)
1744  {
1745    edge=pg[i]-pg[i+1];
1746    boundary[i]=1+abs(gcd(edge[1],edge[2]));
1747  }
1748  // store the values of boundary once more adding the first two at the end
1749  intvec tboundary=boundary,boundary[1],boundary[2];
1750  // sort boundary in an asecending way
1751  intvec sbd=sortintvec(boundary);
1752  // find the first edge having the maximal number of lattice points
1753  int max=maxPosInIntvec(boundary);
1754  // some computations have to be done over the rationals
1755  ring transformationring=0,x,lp;
1756  intvec trans;    // stores the vector by which we have to translate the polygon
1757  intmat A[2][2];  // stores the matrix by which we have to transform the polygon
1758  matrix M[3][3];  // stores the projective coordinates of the points
1759                   // which are to be transformed
1760  matrix N[3][3];  // stores the projective coordinates of the points to
1761                   // which M is to be transformed
1762  intmat T[3][3];  // stores the unimodular affine transformation in
1763                   // projective form
1764  // add the second point of pg once again at the end
1765  pg=insert(pg,pg[2],size(pg));
1766  // if there is only one edge which has the maximal number of lattice points,
1767  // then M should be:
1768  M=pg[max],1,pg[max+1],1,pg[max+2],1;
1769  // consider the 16 different cases which can occur:
1770  // Case 1:
1771  if (sbd==intvec(2,2,2))
1772  {
1773    N=0,1,1,1,2,1,2,0,1;
1774  }
1775  // Case 2:
1776  if (sbd==intvec(2,2,3))
1777  {
1778    N=2,0,1,0,0,1,1,2,1;
1779  }
1780  // Case 3:
1781  if (sbd==intvec(2,3,4))
1782  {
1783    // here the orientation of the Newton polygon is important !
1784    if (tboundary[max+1]==3)
1785    {
1786      N=3,0,1,0,0,1,0,2,1;
1787    }
1788    else
1789    {
1790      N=0,0,1,3,0,1,0,2,1;
1791    }
1792  }
1793  // Case 4:
1794  if (sbd==intvec(3,3,5))
1795  {
1796    N=4,0,1,0,0,1,0,2,1;
1797  }
1798  // Case 5:
1799  if (sbd==intvec(4,4,4))
1800  {
1801    N=3,0,1,0,0,1,0,3,1;
1802  }
1803  // Case 6+7:
1804  if (sbd==intvec(2,2,2,2))
1805  {
1806    // there are two different polygons which has four edges all of length 2,
1807    // but only one of them has two edges whose direction vectors form a matrix
1808    // of determinant 3
1809    A=pg[1]-pg[2],pg[3]-pg[2];
1810    while ((max<4) and (det(A)!=3))
1811    {
1812      max++;
1813      A=pg[max]-pg[max+1],pg[max+2]-pg[max+1];
1814    }
1815    // Case 6:
1816    if (det(A)==3)
1817    {
1818      M=pg[max],1,pg[max+1],1,pg[max+2],1;
1819      N=1,0,1,0,2,1,2,1,1;
1820    }
1821    // Case 7:
1822    else
1823    {
1824      N=2,1,1,1,0,1,0,1,1;
1825    }
1826  }
1827  // Case 8:
1828  if (sbd==intvec(2,2,2,3))
1829  {
1830    // the orientation of the polygon is important
1831    A=pg[max]-pg[max+1],pg[max+2]-pg[max+1];
1832    if (det(A)==2)
1833    {
1834      N=2,0,1,0,0,1,0,1,1;
1835    }
1836    else
1837    {
1838      N=0,0,1,2,0,1,1,2,1;
1839    }
1840  }
1841  // Case 9:
1842  if (sbd==intvec(2,2,3,3))
1843  {
1844    // if max==1, then the 5th entry in tboundary is the same as the first
1845    if (max==1)
1846    {
1847      max=5;
1848    }
1849    // if boundary=3,2,2,3 then set max=4
1850    if (tboundary[max+1]!=3)
1851    {
1852      max=4;
1853    }
1854    M=pg[max],1,pg[max+1],1,pg[max+2],1;
1855    // the orientation of the polygon matters
1856    A=pg[max-1]-pg[max],pg[max+1]-pg[max];
1857    if (det(A)==4)
1858    {
1859      N=2,0,1,0,0,1,0,2,1;
1860    }
1861    else
1862    {
1863      N=0,2,1,0,0,1,2,0,1;
1864    }
1865  }
1866  // Case 10:
1867  if (sbd==intvec(2,2,3,4))
1868  {
1869    // the orientation of the polygon matters
1870    if (tboundary[max+1]==3)
1871    {
1872      N=3,0,1,0,0,1,0,2,1;
1873    }
1874    else
1875    {
1876      N=0,0,1,3,0,1,2,1,1;
1877    }
1878  }
1879  // Case 11:
1880  if (sbd==intvec(2,3,3,4))
1881  {
1882    N=3,0,1,0,0,1,0,2,1;
1883  }
1884  // Case 12:
1885  if (sbd==intvec(3,3,3,3))
1886  {
1887    N=2,0,1,0,0,1,0,2,1;
1888  }
1889  // Case 13:
1890  if (sbd==intvec(2,2,2,2,2))
1891  {
1892    // compute the angles of the polygon vertices
1893    intvec dt;
1894    for (i=1;i<=5;i++)
1895    {
1896      A=pg[i]-pg[i+1],pg[i+2]-pg[i+1];
1897      dt[i]=det(A);
1898    }
1899    dt[6]=dt[1];
1900    // find the vertex to be mapped to (0,1)
1901    max=1;
1902    while ((dt[max]!=2) or (dt[max+1]!=2))
1903    {
1904      max++;
1905    }
1906    M=pg[max],1,pg[max+1],1,pg[max+2],1;
1907    N=0,1,1,1,2,1,2,1,1;
1908  }
1909  // Case 14:
1910  if (sbd==intvec(2,2,2,2,3))
1911  {
1912    N=2,0,1,0,0,1,0,1,1;
1913  }
1914  // Case 15:
1915  if (sbd==intvec(2,2,2,3,3))
1916  {
1917    // find the vertix to be mapped to (2,0)
1918    if (tboundary[max+1]!=3)
1919    {
1920      max=5;
1921      M=pg[max],1,pg[max+1],1,pg[max+2],1;
1922    }
1923    N=2,0,1,0,0,1,0,2,1;
1924  }
1925  // Case 16:
1926  if (sbd==intvec(2,2,2,2,2,2))
1927  {
1928    N=2,0,1,1,0,1,0,1,1;
1929  }
1930  // we have to transpose the matrices M and N
1931  M=transpose(M);
1932  N=transpose(N);
1933  // compute the unimodular affine transformation, which is of the form
1934  // A11 A12 | T1
1935  // A21 A22 | T2
1936  //  0   0  | 1
1937  T=matrixtointmat(N*inverse(M));
1938  // the upper-left 2x2-block is A
1939  A=T[1..2,1..2];
1940  // the upper-right 2x1-block is the translation vector
1941  trans=T[1,3],T[2,3];
1942  // transform now the lattice points of the polygon with respect to A and T
1943  list nf;
1944  for (i=1;i<=size(polygon);i++)
1945  {
1946    intmat V[2][1]=polygon[i];
1947    V=A*V;
1948    nf[i]=intvec(V[1,1]+trans[1],V[2,1]+trans[2]);
1949    kill V;
1950  }
1951  return(list(findOrientedBoundary(nf)[2],A,trans,nf));
1952}
1953example
1954{
1955   "EXAMPLE:";
1956   echo=2;
1957   ring r=0,(x,y),dp;
1958   // the Newton polygon of the following polynomial
1959   //     has precisely one interior point
1960   poly f=x22y11+x19y10+x17y9+x16y9+x12y7+x9y6+x7y5+x2y3;
1961   list polygon=newtonPolytopeLP(f);
1962   // its lattice points are
1963   polygon;
1964   // find its normal form
1965   list nf=ellipticNF(polygon);
1966   // the vertices of the normal form are
1967   nf[1];
1968   // it has been transformed by the unimodular affine transformation A*x+v
1969   // with matrix A
1970   nf[2];
1971   // and translation vector v
1972   nf[3];
1973   // the 3rd lattice point ...
1974   polygon[3];
1975   // ... has been transformed to
1976   nf[4][3];
1977}
1978
1979
1980/////////////////////////////////////////////////////////////////////////////
1981
1982proc ellipticNFDB (int n,list #)
1983"USAGE:  ellipticNFDB(n[,#]);   n int, # list
1984ASSUME:  n is an integer between 1 and 16
1985PURPOSE: this is a database storing the 16 normal forms of planar polygons with
1986         precisely one interior point up to unimodular affine transformations
1987@*       (see e.g. Bjorn Poonen, Fernando Rodriguez-Villegas: Lattice Polygons
1988                   and the number 12.  Amer. Math. Monthly  107  (2000),  no. 3,
1989                   238--250.)
1990RETURN:  list, L such that
1991@*             L[1] : list whose entries are the vertices of the nth normal form
1992@*             L[2] : list whose entries are all the lattice points of the
1993                      nth normal form
1994@*             L[3] : only present if the optional parameter # is present, and
1995                      then it is a polynomial in the variables (x,y) whose
1996                      Newton polygon is the nth normal form
1997NOTE:    the optional parameter is only allowed if the basering has the
1998         variables x and y
1999EXAMPLE: example ellipticNFDB;   shows an example"
2000{
2001  if ((n<1) or (n>16))
2002  {
2003    ERROR("n is not between 1 and 16.");
2004  }
2005  if (size(#)>0)
2006  {
2007    if ((defined(x)==0) or (defined(y)==0))
2008    {
2009      ERROR("The variables x and y are not defined.");
2010    }
2011  }
2012  if ((defined(x)==0) or (defined(y)==0))
2013  {
2014    ring nfring=0,(x,y),dp;
2015  }
2016  // store the normal forms as polynomials
2017  list nf=x2+y+xy2,x2+x+1+xy2,x3+x2+x+1+y2+y,x4+x3+x2+x+1+y2+y+x2y,x3+x2+x+1+x2y+y+xy2+y2+y3,
2018    x2+x+x2y+y2,x2y+x+y+xy2,x2+x+1+y+xy2,x2+x+1+y+xy2+y2,x3+x2+x+1+x2y+y+y2,x3+x2+x+1+x2y+y+xy2+y2,
2019    x2+x+1+x2y+y+x2y2+xy2+y2,x+1+x2y+y+xy2,x2+x+1+x2y+y+xy2,x2+x+1+x2y+y+xy2+y2,x2+x+x2y+y+xy2+y2;
2020  list pg=newtonPolytopeLP(nf[n]);
2021  if (size(#)==0)
2022  {
2023    return(list(findOrientedBoundary(pg)[2],pg));
2024  }
2025  else
2026  {
2027    return(list(findOrientedBoundary(pg)[2],pg,nf[n]));
2028  }
2029}
2030example
2031{
2032   "EXAMPLE:";
2033   echo=2;
2034   list nf=ellipticNFDB(5);
2035   // the vertices of the 5th normal form are
2036   nf[1];
2037   // its lattice points are
2038   nf[2];
2039}
2040
2041
2042/////////////////////////////////////////////////////////////////////////////////
2043/////////////////////////////////////////////////////////////////////////////////
2044/// AUXILARY PROCEDURES, WHICH ARE DECLARED STATIC
2045/////////////////////////////////////////////////////////////////////////////////
2046/////////////////////////////////////////////////////////////////////////////////
2047/// - scalarproduct
2048/// - intmatcoldelete
2049/// - intmatconcat
2050/// - sortlist
2051/// - minInList
2052/// - stringdelete
2053/// - abs
2054/// - commondenominator
2055/// - maxPosInIntvec
2056/// - maxPosInIntmat
2057/// - sortintvec
2058/// - matrixtointmat
2059/////////////////////////////////////////////////////////////////////////////////
2060
2061static proc scalarproduct (intvec w,intvec v)
2062"USAGE:      scalarproduct(w,v); w,v intvec
2063ASSUME:      w and v are integer vectors of the same length
2064RETURN:      int, the scalarproduct of v and w
2065NOTE:        the procedure is called by findOrientedBoundary"
2066{
2067  int sp;
2068  for (int i=1;i<=size(w);i++)
2069  {
2070    sp=sp+v[i]*w[i];
2071  }
2072  return(sp);
2073}
2074
2075static proc intmatcoldelete (def w,int i)
2076"USAGE:      intmatcoldelete(w,i); w intmat, i int
2077RETURN:      intmat, the integer matrix w with the ith comlumn deleted
2078NOTE:        the procedure is called by intmatsort and normalFanL"
2079{
2080  if (typeof(w)=="intmat")
2081  {
2082    if ((i<1) or (i>ncols(w)) or (ncols(w)==1))
2083    {
2084      return(w);
2085    }
2086    if (i==1)
2087    {
2088      intmat M[nrows(w)][ncols(w)-1]=w[1..nrows(w),2..ncols(w)];
2089      return(M);
2090    }
2091    if (i==ncols(w))
2092    {
2093      intmat M[nrows(w)][ncols(w)-1]=w[1..nrows(w),1..ncols(w)-1];
2094      return(M);
2095    }
2096    else
2097    {
2098      intmat M[nrows(w)][i-1]=w[1..nrows(w),1..i-1];
2099      intmat N[nrows(w)][ncols(w)-i]=w[1..nrows(w),i+1..ncols(w)];
2100      return(intmatconcat(M,N));
2101    }
2102  }
2103  if (typeof(w)=="bigintmat")
2104  {
2105    if ((i<1) or (i>ncols(w)) or (ncols(w)==1))
2106    {
2107      return(w);
2108    }
2109    if (i==1)
2110    {
2111      bigintmat M[nrows(w)][ncols(w)-1]=w[1..nrows(w),2..ncols(w)];
2112      return(M);
2113    }
2114    if (i==ncols(w))
2115    {
2116      bigintmat M[nrows(w)][ncols(w)-1]=w[1..nrows(w),1..ncols(w)-1];
2117      return(M);
2118    }
2119    else
2120    {
2121      bigintmat MN[nrows(w)][ncols(w)-1];
2122      MN[1..nrows(w),1..i-1]=w[1..nrows(w),1..i-1];
2123      MN[1..nrows(w),i..ncols(w)-1]=w[1..nrows(w),i+1..ncols(w)];
2124      return(MN);
2125    }
2126  } else
2127  {
2128    ERROR("intmatcoldelete: input matrix has to be of type intmat or bigintmat");
2129    intmat M; return(M);
2130  }
2131}
2132
2133static proc intmatconcat (intmat M,intmat N)
2134"USAGE:      intmatconcat(M,N); M,N intmat
2135RETURN:      intmat, M and N concatenated
2136NOTE:        the procedure is called by intmatcoldelete and sortintmat"
2137{
2138  if (nrows(M)>=nrows(N))
2139  {
2140    int m=nrows(M);
2141
2142  }
2143  else
2144  {
2145    int m=nrows(N);
2146  }
2147  intmat P[m][ncols(M)+ncols(N)];
2148  P[1..nrows(M),1..ncols(M)]=M[1..nrows(M),1..ncols(M)];
2149  P[1..nrows(N),ncols(M)+1..ncols(M)+ncols(N)]=N[1..nrows(N),1..ncols(N)];
2150  return(P);
2151}
2152
2153static proc sortlist (list v,int pos)
2154"USAGE:      sortlist(v,pos); v list, pos int
2155RETURN:      list, the list L ordered in an ascending way according to the pos-th entries
2156NOTE:        called by tropicalCurve"
2157{
2158  if(size(v)==1)
2159  {
2160    return(v);
2161  }
2162  list w=minInList(v,pos);
2163  v=delete(v,w[2]);
2164  v=sortlist(v,pos);
2165  v=list(w[1])+v;
2166  return(v);
2167}
2168
2169static proc minInList (list v,int pos)
2170"USAGE:      minInList(v,pos); v list, pos int
2171RETURN:      list, (v[i],i) such that v[i][pos] is minimal
2172NOTE:        called by sortlist"
2173{
2174  int min=v[1][pos];
2175  int minpos=1;
2176  for (int i=2;i<=size(v);i++)
2177  {
2178    if (v[i][pos]<min)
2179    {
2180      min=v[i][pos];
2181      minpos=i;
2182    }
2183  }
2184  return(list(v[minpos],minpos));
2185}
2186
2187static proc stringdelete (string w,int i)
2188"USAGE:      stringdelete(w,i); w string, i int
2189RETURN:      string, the string w with the ith component deleted
2190NOTE:        the procedure is called by texnumber and choosegfanvector"
2191{
2192  if ((i>size(w)) or (i<=0))
2193  {
2194    return(w);
2195  }
2196  if ((size(w)==1) and (i==1))
2197  {
2198    return("");
2199
2200  }
2201  if (i==1)
2202  {
2203    return(w[2..size(w)]);
2204  }
2205  if (i==size(w))
2206  {
2207    return(w[1..size(w)-1]);
2208  }
2209  else
2210  {
2211    string erg=w[1..i-1],w[i+1..size(w)];
2212    return(erg);
2213  }
2214}
2215
2216static proc abs (def n)
2217"USAGE:      abs(n); n poly or int
2218RETURN:      poly or int, the absolute value of n"
2219{
2220  if (n>=0)
2221  {
2222    return(n);
2223  }
2224  else
2225  {
2226    return(-n);
2227  }
2228}
2229
2230static proc commondenominator (matrix M)
2231"USAGE:   commondenominator(M);  M matrix
2232ASSUME:   the base ring has characteristic zero
2233RETURN:   int, the lowest common multiple of the denominators of the leading coefficients
2234               of the entries in M
2235NOTE:        the procedure is called from polymakeToIntmat"
2236{
2237  int i,j;
2238  int kgV=1;
2239  // successively build the lowest common multiple of the denominators of the leading coefficients
2240  // of the entries in M
2241  for (i=1;i<=nrows(M);i++)
2242  {
2243    for (j=1;j<=ncols(M);j++)
2244    {
2245      kgV=lcm(kgV,int(denominator(leadcoef(M[i,j]))));
2246    }
2247  }
2248  return(kgV);
2249}
2250
2251static proc maxPosInIntvec (intvec v)
2252"USAGE:      maxPosInIntvec(v); v intvec
2253RETURN:      int, the first position of a maximal entry in v
2254NOTE:        called by sortintmat"
2255{
2256  int max=v[1];
2257  int maxpos=1;
2258  for (int i=2;i<=size(v);i++)
2259  {
2260    if (v[i]>max)
2261    {
2262      max=v[i];
2263      maxpos=i;
2264    }
2265  }
2266  return(maxpos);
2267}
2268
2269static proc maxPosInIntmat (intmat v)
2270"USAGE:      maxPosInIntmat(v); v intmat
2271ASSUME:      v has a unique maximal entry
2272RETURN:      intvec, the position (i,j) of the maximal entry in v
2273NOTE:        called by findOrientedBoundary"
2274{
2275  int max=v[1,1];
2276  intvec maxpos=1,1;
2277  int i,j;
2278  for (i=1;i<=nrows(v);i++)
2279  {
2280    for (j=1;j<=ncols(v);j++)
2281    {
2282      if (v[i,j]>max)
2283      {
2284        max=v[i,j];
2285        maxpos=i,j;
2286      }
2287    }
2288  }
2289  return(maxpos);
2290}
2291
2292static proc sortintvec (intvec w)
2293"USAGE:      sortintvec(v); v intvec
2294RETURN:      intvec, the entries of v are ordered in an ascending way
2295NOTE:        called from ellipticNF"
2296{
2297  int j,k,stop;
2298  intvec v=w[1];
2299  for (j=2;j<=size(w);j++)
2300  {
2301    k=1;
2302    stop=0;
2303    while ((k<=size(v)) and (stop==0))
2304    {
2305      if (v[k]<w[j])
2306      {
2307        k++;
2308      }
2309      else
2310      {
2311        stop=1;
2312      }
2313    }
2314    if (k==size(v)+1)
2315    {
2316      v=v,w[j];
2317    }
2318    else
2319    {
2320      if (k==1)
2321      {
2322        v=w[j],v;
2323      }
2324      else
2325      {
2326        v=v[1..k-1],w[j],v[k..size(v)];
2327      }
2328    }
2329  }
2330  return(v);
2331}
2332
2333static proc sortlistbyintvec (list L,intvec w)
2334"USAGE:      sortlistbyintvec(L,w); L list, w intvec
2335RETURN:      list, the entries of L are ordered such that the corresponding reordering of
2336                   w would order w in an ascending way
2337NOTE:        called from ellipticNF"
2338{
2339  int j,k,stop;
2340  intvec v=w[1];
2341  list LL=L[1];
2342  for (j=2;j<=size(w);j++)
2343  {
2344    k=1;
2345    stop=0;
2346    while ((k<=size(v)) and (stop==0))
2347    {
2348      if (v[k]<w[j])
2349      {
2350        k++;
2351      }
2352      else
2353      {
2354        stop=1;
2355      }
2356    }
2357    if (k==size(v)+1)
2358    {
2359      v=v,w[j];
2360      LL=insert(LL,L[j],size(LL));
2361    }
2362    else
2363    {
2364      if (k==1)
2365      {
2366        v=w[j],v;
2367        LL=insert(LL,L[j]);
2368      }
2369      else
2370      {
2371        v=v[1..k-1],w[j],v[k..size(v)];
2372        LL=insert(LL,L[j],k-1);
2373      }
2374    }
2375  }
2376  return(LL);
2377}
2378
2379static proc matrixtointmat (matrix MM)
2380"USAGE:      matrixtointmat(v); MM matrix
2381ASSUME:      MM is a matrix with only integers as entries
2382RETURN:      intmat, the matrix MM has been transformed to type intmat
2383NOTE:        called from ellipticNF"
2384{
2385  intmat M[nrows(MM)][ncols(MM)]=M;
2386  int i,j;
2387  for (i=1;i<=nrows(M);i++)
2388  {
2389    for (j=1;j<=ncols(M);j++)
2390    {
2391      execute("M["+string(i)+","+string(j)+"]="+string(MM[i,j])+";");
2392    }
2393  }
2394  return(M);
2395}
2396
2397//////////////////////////////////////////////////////////////////////////////
2398
2399static proc polygonToCoordinates (list points)
2400"USAGE:      polygonToCoordinates(points);   points list
2401ASSUME:      points is a list of integer vectors each of size two describing the
2402             marked points of a convex lattice polygon like the output of
2403             polygonDB
2404RETURN:      list, the first entry is a string representing the coordinates
2405                   corresponding to the latticpoints seperated by commata
2406                   the second entry is a list where the ith entry is a string
2407                   representing the coordinate of corresponding to the ith
2408                   lattice point the third entry is the latex format of the
2409                   first entry
2410NOTE:        the procedure is called by fan"
2411{
2412  string coord;
2413  list coords;
2414  string latex;
2415  for (int i=1;i<=size(points);i++)
2416  {
2417    coords[i]="u"+string(points[i][1])+string(points[i][2]);
2418    coord=coord+coords[i]+",";
2419    latex=latex+"u_{"+string(points[i][1])+string(points[i][2])+"},";
2420  }
2421  coord=coord[1,size(coord)-1];
2422  latex=latex[1,size(latex)-1];
2423  return(list(coord,coords,latex));
2424}
2425
2426static proc intmatAddFirstColumn (def M,string art)
2427"USAGE:  intmatAddFirstColumn(M,art);  M intmat, art string
2428ASSUME:  - M is an integer matrix where a first column of 0's or 1's should be added
2429@*       - art is one of the following strings:
2430@*         + 'rays'   : indicating that a first column of 0's should be added
2431@*         + 'points' : indicating that a first column of 1's should be added
2432RETURN:  intmat, a first column has been added to the matrix"
2433{
2434  if (typeof (M) == "intmat")
2435  {
2436    intmat N[nrows(M)][ncols(M)+1];
2437    int i,j;
2438    for (i=1;i<=nrows(M);i++)
2439    {
2440      if (art=="rays")
2441      {
2442        N[i,1]=0;
2443      }
2444      else
2445      {
2446        N[i,1]=1;
2447      }
2448      for (j=1;j<=ncols(M);j++)
2449      {
2450        N[i,j+1]=M[i,j];
2451      }
2452    }
2453    return(N);
2454  }
2455  if (typeof (M) == "bigintmat")
2456  {
2457    bigintmat N[nrows(M)][ncols(M)+1];
2458    int i,j;
2459    for (i=1;i<=nrows(M);i++)
2460    {
2461      if (art=="rays")
2462      {
2463        N[i,1]=0;
2464      }
2465      else
2466      {
2467        N[i,1]=1;
2468      }
2469      for (j=1;j<=ncols(M);j++)
2470      {
2471        N[i,j+1]=M[i,j];
2472      }
2473    }
2474    return(N);
2475  }
2476  else
2477  {
2478    ERROR ("intmatAddFirstColumn: input matrix has to be either intmat or bigintmat");
2479    intmat N;
2480    return (N);
2481  }
2482}
2483
2484
2485
Note: See TracBrowser for help on using the repository browser.