[BACK]Return to volumes.adb CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / Ada / Root_Counts / Implift

Annotation of OpenXM_contrib/PHC/Ada/Root_Counts/Implift/volumes.adb, Revision 1.1

1.1     ! maekawa     1: with Standard_Integer_Vectors;           use Standard_Integer_Vectors;
        !             2: with Standard_Integer_Norms;             use Standard_Integer_Norms;
        !             3: with Standard_Integer_VecVecs;           use Standard_Integer_VecVecs;
        !             4: with Standard_Integer_Matrices;          use Standard_Integer_Matrices;
        !             5: with Standard_Integer_Linear_Solvers;    use Standard_Integer_Linear_Solvers;
        !             6: with Transformations;                    use Transformations;
        !             7: with Transforming_Integer_Vector_Lists;  use Transforming_Integer_Vector_Lists;
        !             8: with Integer_Vectors_Utilities;          use Integer_Vectors_Utilities;
        !             9: with Integer_Support_Functions;          use Integer_Support_Functions;
        !            10: with Integer_Face_Enumerators;           use Integer_Face_Enumerators;
        !            11: with Lists_of_Vectors_Utilities;         use Lists_of_Vectors_Utilities;
        !            12: with Arrays_of_Lists_Utilities;          use Arrays_of_Lists_Utilities;
        !            13: --with Face_Enumerator_of_Sum;             use Face_Enumerator_of_Sum;
        !            14:
        !            15: package body Volumes is
        !            16:
        !            17: -- INVARIANT CONDITION :
        !            18: --   In order to get p(v) > 0, the zero vector must be in the first list,
        !            19: --   so shifting is necessary.
        !            20: --   The shift vector must be equal to the maximal element in the list,
        !            21: --   w.r.t. the graded lexicographic ordening.
        !            22: --   In this way, the shift vector is unique, which allows to `mirror'
        !            23: --   the same operations for the mixed homotopy continuation.
        !            24:
        !            25: -- AUXILIARIES :
        !            26:
        !            27:   function Create_Facet ( n : natural; facet : Vector; pts : VecVec )
        !            28:                         return VecVec is
        !            29:
        !            30:     res : VecVec(1..n);
        !            31:     cnt : natural := 0;
        !            32:
        !            33:   begin
        !            34:     for i in facet'range loop
        !            35:       cnt := cnt+1;
        !            36:       res(cnt) := pts(facet(i));
        !            37:     end loop;
        !            38:     return res;
        !            39:   end Create_Facet;
        !            40:
        !            41:   function Determinant ( vv : VecVec ) return integer is
        !            42:
        !            43:     a : Matrix(vv'range,vv'range);
        !            44:
        !            45:   begin
        !            46:     for k in a'range(1) loop
        !            47:       for l in a'range(2) loop
        !            48:         a(k,l) := vv(k)(l);
        !            49:       end loop;
        !            50:     end loop;
        !            51:    -- Upper_Triangulate(a);
        !            52:     return Det(a);
        !            53:   end Determinant;
        !            54:
        !            55: -- VOLUME COMPUTATIONS :
        !            56:
        !            57:   function Vol ( n : natural; l : List ) return natural is
        !            58:
        !            59:   -- DESCRIPTION :
        !            60:   --   Computes the volume of the simplex spanned by the list
        !            61:   --   and the origin.
        !            62:
        !            63:     res : integer;
        !            64:     vv : VecVec(1..n);
        !            65:     tmp : List;
        !            66:
        !            67:   begin
        !            68:     tmp := l;
        !            69:     for i in vv'range loop
        !            70:       vv(i) := Head_Of(tmp);
        !            71:       tmp := Tail_Of(tmp);
        !            72:     end loop;
        !            73:     res := Determinant(vv);
        !            74:     if res < 0
        !            75:      then return -res;
        !            76:      else return res;
        !            77:     end if;
        !            78:   end Vol;
        !            79:
        !            80:   function Volume ( n,i : natural; l : List; v : Vector; pv : integer )
        !            81:                   return natural is
        !            82:
        !            83:   -- DESCRIPTION :
        !            84:   --   The points in l all belong to the same hyperplane:
        !            85:   --    < x , v > - pv = 0;
        !            86:   --   this procedure computes the volume of the polytope generated by
        !            87:   --   the points in l and the origin.
        !            88:
        !            89:     ll : natural := Length_Of(l);
        !            90:
        !            91:   begin
        !            92:     if ll < n
        !            93:      then return 0;
        !            94:      elsif ll = n
        !            95:         then return Vol(n,l);
        !            96:          else declare
        !            97:                t : Transfo;
        !            98:                tl,rl : List;
        !            99:                vl : integer;
        !           100:               begin
        !           101:                if pv > 0
        !           102:                 then t := Build_Transfo(v,i);
        !           103:                       tl := t*l;
        !           104:                      rl := Reduce(tl,i);
        !           105:                       Clear(t); Deep_Clear(tl);
        !           106:                      -- Remove_Duplicates(rl);
        !           107:                       if Length_Of(rl) >= n-1
        !           108:                        then vl := pv*Volume(n-1,rl);
        !           109:                        else vl := 0;
        !           110:                       end if;
        !           111:                      Deep_Clear(rl);
        !           112:                      return vl;
        !           113:                  else return 0;
        !           114:                 end if;
        !           115:               end;
        !           116:     end if;
        !           117:   end Volume;
        !           118:
        !           119:   function Sum ( n,m : natural; l : List ) return natural is
        !           120:
        !           121:   -- DESCRIPTION :
        !           122:   --   Computes the volume of the polytope generated by the points in l;
        !           123:   --   where n > 1 and n < m = Length_Of(l).
        !           124:
        !           125:     res : natural;
        !           126:     fix : Link_to_Vector;
        !           127:     pts : VecVec(1..m-1);
        !           128:     nulvec : Vector(1..n) := (1..n => 0);
        !           129:     vl,wl,vl_last : List;
        !           130:     sh : boolean;
        !           131:
        !           132:     procedure Compute_Facet ( facet : in vector; cont : out boolean ) is
        !           133:
        !           134:       vv : constant VecVec := Create_Facet(n,facet,pts);
        !           135:       pl : List;
        !           136:       v : Link_to_Vector;
        !           137:       i,pv,sup : integer;
        !           138:
        !           139:     begin
        !           140:       v := Compute_Normal(vv);
        !           141:       i := Pivot(v);
        !           142:       if i <= v'last
        !           143:        then pv := vv(vv'first)*v;
        !           144:            if pv < 0
        !           145:             then for j in v'range loop
        !           146:                    v(j) := -v(j);
        !           147:                   end loop;
        !           148:                  pv := -pv;
        !           149:             end if;
        !           150:            if (pv > 0) and then not Is_In(vl,v)
        !           151:              then sup := Maximal_Support(wl,v.all);
        !           152:                  if sup = pv
        !           153:                   then Append(vl,vl_last,v);
        !           154:                        pl := Face(wl,v.all,pv);
        !           155:                        res := res + Volume(n,i,pl,v.all,pv);
        !           156:                        Deep_Clear(pl);
        !           157:                   end if;
        !           158:             end if;
        !           159:       end if;
        !           160:       cont := true;
        !           161:     end Compute_Facet;
        !           162:
        !           163:     procedure Compute_Facets is new Enumerate_Faces(Compute_Facet);
        !           164:
        !           165:   begin
        !           166:     res := 0;
        !           167:     if not Is_In(l,nulvec)
        !           168:      then fix := Graded_Max(l);
        !           169:           wl := Shift(l,fix); sh := true;
        !           170:      else wl := l;            sh := false;
        !           171:     end if;
        !           172:     Move_to_Front(wl,nulvec);
        !           173:     pts := Shallow_Create(Tail_Of(wl));
        !           174:     Compute_Facets(n-1,pts);
        !           175:     Deep_Clear(vl);
        !           176:     if sh
        !           177:      then Deep_Clear(wl); Clear(fix);
        !           178:     end if;
        !           179:     return res;
        !           180:   end Sum;
        !           181:
        !           182:   function Volume ( n : natural; l : List ) return natural is
        !           183:     m : natural;
        !           184:   begin
        !           185:     if n = 1
        !           186:      then declare
        !           187:             min,max : integer := 0;
        !           188:            d : Link_to_Vector := Head_Of(l);
        !           189:           begin
        !           190:            Min_Max(l,d'first,min,max);
        !           191:            return (max - min);
        !           192:           end;
        !           193:      else m := Length_Of(l);
        !           194:          if m <= n
        !           195:           then return 0;
        !           196:           else return Sum(n,m,l);
        !           197:           end if;
        !           198:     end if;
        !           199:   end Volume;
        !           200:
        !           201:   function Volume ( n,i : natural; l : List; v : Vector;
        !           202:                     pv : integer; tv : Tree_of_Vectors ) return natural is
        !           203:
        !           204:   -- DESCRIPTION :
        !           205:   --   The points in l all belong to the same hyperplane:
        !           206:   --    < x , v > - pv = 0;
        !           207:   --   this procedure computes the volume of the polytope generated by
        !           208:   --   the points in l and the origin.
        !           209:
        !           210:     ll : natural := Length_Of(l);
        !           211:
        !           212:   begin
        !           213:     if ll < n
        !           214:      then return 0;
        !           215:      elsif ll = n
        !           216:         then return Vol(n,l);
        !           217:          else declare
        !           218:                t : Transfo;
        !           219:                tl,rl : List;
        !           220:                vl : integer;
        !           221:               begin
        !           222:                if pv > 0
        !           223:                 then t := Build_Transfo(v,i);
        !           224:                       tl := t*l;
        !           225:                      rl := Reduce(tl,i);
        !           226:                       Clear(t); Deep_Clear(tl);
        !           227:                      -- Remove_Duplicates(rl);
        !           228:                       if Length_Of(rl) >= n-1
        !           229:                        then vl := pv*Volume(n-1,rl,tv);
        !           230:                        else vl := 0;
        !           231:                       end if;
        !           232:                      Deep_Clear(rl);
        !           233:                      return vl;
        !           234:                  else return 0;
        !           235:                 end if;
        !           236:               end;
        !           237:     end if;
        !           238:   end Volume;
        !           239:
        !           240:   function Sum ( n,m : natural; l : List; tv : Tree_of_Vectors )
        !           241:               return natural is
        !           242:
        !           243:   -- DESCRIPTION :
        !           244:   --   Computes the volume of the polytope generated by the points in l;
        !           245:   --   where n > 1 and n < m = Length_Of(l).
        !           246:   --   The tree of degrees tv is not empty.
        !           247:
        !           248:     res : natural;
        !           249:     fix : Link_to_Vector;
        !           250:     nulvec : Vector(1..n) := (1..n => 0);
        !           251:     wl : List;
        !           252:     tmp : Tree_of_Vectors;
        !           253:     sh : boolean;
        !           254:
        !           255:   begin
        !           256:     res := 0;
        !           257:     if not Is_In(l,nulvec)
        !           258:      then fix := Graded_Max(l);
        !           259:           wl := Shift(l,fix); sh := true;
        !           260:      else wl := l;            sh := false;
        !           261:     end if;
        !           262:     Move_to_Front(wl,nulvec);
        !           263:     tmp := tv;
        !           264:     while not Is_Null(tmp) loop
        !           265:       declare
        !           266:        nd : node := Head_Of(tmp);
        !           267:        v : Link_to_Vector := nd.d;
        !           268:        pv,i : integer;
        !           269:        pl : List;
        !           270:       begin
        !           271:        i := Pivot(v);
        !           272:        pv := Maximal_Support(wl,v.all);
        !           273:        pl := Face(wl,v.all,pv);
        !           274:        if (nd.ltv = null) or else Is_Null(nd.ltv.all)
        !           275:         then res := res + Volume(n,i,pl,v.all,pv);
        !           276:         else res := res + Volume(n,i,pl,v.all,pv,nd.ltv.all);
        !           277:         end if;
        !           278:        Deep_Clear(pl);
        !           279:       end;
        !           280:       tmp := Tail_Of(tmp);
        !           281:     end loop;
        !           282:     if sh
        !           283:      then Deep_Clear(wl); Clear(fix);
        !           284:     end if;
        !           285:     return res;
        !           286:   end Sum;
        !           287:
        !           288:   function Volume ( n : natural; l : List; tv : Tree_of_Vectors )
        !           289:                   return natural is
        !           290:     m : natural;
        !           291:   begin
        !           292:     if n = 1
        !           293:      then declare
        !           294:             min,max : integer := 0;
        !           295:            d : Link_to_Vector := Head_Of(l);
        !           296:           begin
        !           297:            Min_Max(l,d'first,min,max);
        !           298:            return (max - min);
        !           299:           end;
        !           300:      else m := Length_Of(l);
        !           301:          if m <= n
        !           302:           then return 0;
        !           303:           elsif not Is_Null(tv)
        !           304:               then return Sum(n,m,l,tv);
        !           305:               else return Sum(n,m,l);
        !           306:           end if;
        !           307:     end if;
        !           308:   end Volume;
        !           309:
        !           310:   procedure Volume ( n,i : in natural; l : in List; v : in Vector;
        !           311:                      pv : in integer; tv : in out Tree_of_Vectors;
        !           312:                      vlm : out natural ) is
        !           313:
        !           314:   -- DESCRIPTION :
        !           315:   --   The points in l all belong to the same hyperplane:
        !           316:   --    < x , v > - pv = 0;
        !           317:   --   this procedure computes the volume of the polytope generated by
        !           318:   --   the points in l and the origin.
        !           319:
        !           320:     ll : natural := Length_Of(l);
        !           321:     vl : natural;
        !           322:
        !           323:   begin
        !           324:     if ll < n
        !           325:      then vlm := 0;
        !           326:      elsif ll = n
        !           327:         then vl := Vol(n,l);
        !           328:               if vl > 0
        !           329:                then declare
        !           330:                       nd : node;
        !           331:                     begin
        !           332:                       nd.d := new Vector'(v);
        !           333:                       Construct(nd,tv);
        !           334:                     end;
        !           335:               end if;
        !           336:              vlm := vl;
        !           337:          else declare
        !           338:                t : Transfo;
        !           339:                tl,rl : List;
        !           340:               begin
        !           341:                if pv > 0
        !           342:                 then t := Build_Transfo(v,i);
        !           343:                       tl := t*l;
        !           344:                       rl := Reduce(tl,i);
        !           345:                       Clear(t); Deep_Clear(tl);
        !           346:                      -- Remove_Duplicates(rl);
        !           347:                       if Length_Of(rl) >= n-1
        !           348:                        then declare
        !           349:                               tmp : Tree_of_Vectors;
        !           350:                             begin
        !           351:                               Volume(n-1,rl,tmp,vl);
        !           352:                               if vl = 0
        !           353:                                then Clear(tmp);
        !           354:                                else
        !           355:                                  declare
        !           356:                                    nd : node;
        !           357:                                  begin
        !           358:                                    nd.d := new Vector'(v);
        !           359:                                    if not Is_Null(tmp)
        !           360:                                     then nd.ltv := new Tree_of_Vectors'(tmp);
        !           361:                                    end if;
        !           362:                                    Construct(nd,tv);
        !           363:                                  end;
        !           364:                               end if;
        !           365:                             end;
        !           366:                             vlm := pv*vl;
        !           367:                        else vlm := 0;
        !           368:                       end if;
        !           369:                       Deep_Clear(rl);
        !           370:                  else vlm := 0;
        !           371:                 end if;
        !           372:               end;
        !           373:     end if;
        !           374:   end Volume;
        !           375:
        !           376:   procedure Sum ( n,m : in natural; l : in List;
        !           377:                  tv : in out Tree_of_Vectors; vlm : out natural ) is
        !           378:
        !           379:   -- DESCRIPTION :
        !           380:   --   Computes the volume of the polytope generated by the points in l;
        !           381:   --   where n > 1 and n < m = Length_Of(l).
        !           382:
        !           383:     res : natural;
        !           384:     pts : VecVec(1..m-1);
        !           385:     fix : Link_to_Vector;
        !           386:     nulvec : Vector(1..n) := (1..n => 0);
        !           387:     wl : List;
        !           388:     sh : boolean;
        !           389:
        !           390:     procedure Compute_Facet ( facet : in vector; cont : out boolean ) is
        !           391:
        !           392:       vv : constant VecVec := Create_Facet(n,facet,pts);
        !           393:       pl : List;
        !           394:       v : Link_to_Vector;
        !           395:       i,pv,sup,pvol : integer;
        !           396:
        !           397:     begin
        !           398:       v := Compute_Normal(vv);
        !           399:       i := Pivot(v);
        !           400:       if i <= v'last
        !           401:        then pv := vv(vv'first)*v;
        !           402:            if pv < 0
        !           403:             then for j in v'range loop
        !           404:                    v(j) := -v(j);
        !           405:                   end loop;
        !           406:                  pv := -pv;
        !           407:             end if;
        !           408:            if (pv > 0) and then not Is_In(tv,v)
        !           409:              then sup := Maximal_Support(wl,v.all);
        !           410:                  if sup = pv
        !           411:                   then pl := Face(wl,v.all,pv);
        !           412:                        Volume(n,i,pl,v.all,pv,tv,pvol);
        !           413:                        res := res + pvol;
        !           414:                        Deep_Clear(pl);
        !           415:                   end if;
        !           416:             end if;
        !           417:       end if;
        !           418:       cont := true;
        !           419:     end Compute_Facet;
        !           420:
        !           421:     procedure Compute_Facets is new Enumerate_Faces(Compute_Facet);
        !           422:
        !           423:   begin
        !           424:     res := 0;
        !           425:     if not Is_In(l,nulvec)
        !           426:      then fix := Graded_Max(l);
        !           427:           wl := Shift(l,fix); sh := true;
        !           428:      else wl := l;            sh := false;
        !           429:     end if;
        !           430:     Move_to_Front(wl,nulvec);
        !           431:     pts := Shallow_Create(Tail_Of(wl));
        !           432:     Compute_Facets(n-1,pts);
        !           433:     if sh
        !           434:      then Deep_Clear(wl); Clear(fix);
        !           435:     end if;
        !           436:     vlm := res;
        !           437:   end Sum;
        !           438:
        !           439:   procedure Volume ( n : in natural; l : in List;
        !           440:                     tv : in out Tree_of_Vectors; vlm : out natural ) is
        !           441:     m : natural;
        !           442:   begin
        !           443:     if n = 1
        !           444:      then declare
        !           445:             min,max : integer := 0;
        !           446:            d : Link_to_Vector := Head_Of(l);
        !           447:           begin
        !           448:            Min_Max(l,d'first,min,max);
        !           449:            vlm := max - min;
        !           450:           end;
        !           451:      else m := Length_Of(l);
        !           452:          if m <= n
        !           453:           then vlm := 0;
        !           454:           else Sum(n,m,l,tv,vlm);
        !           455:           end if;
        !           456:     end if;
        !           457:   end Volume;
        !           458:
        !           459: -- MIXED VOLUME COMPUTATIONS WITHOUT TREE OF USEFUL DIRECTIONS :
        !           460:
        !           461:   function Two_Terms_Mixed_Vol ( n : natural; al : Array_of_Lists )
        !           462:                               return natural is
        !           463:
        !           464:   -- DESCRIPTION :
        !           465:   --   returns the mixed volume of the polytopes generated by the
        !           466:   --   points in al, where the first polytope is generated by only
        !           467:   --   two points.
        !           468:
        !           469:     first,second : Link_to_Vector;
        !           470:     l : List renames al(al'first);
        !           471:     res : natural;
        !           472:
        !           473:   begin
        !           474:     first := Head_Of(l);
        !           475:     second := Head_Of(Tail_Of(l));
        !           476:     declare
        !           477:       d : Vector(first'range);
        !           478:       piv : integer := 0;
        !           479:     begin
        !           480:       for i in d'range loop
        !           481:        d(i) := first(i) - second(i);
        !           482:        if (piv = 0) and then (d(i) /= 0)
        !           483:         then piv := i;
        !           484:         end if;
        !           485:       end loop;
        !           486:       if piv = 0
        !           487:        then return 0;
        !           488:        else if d(piv) < 0
        !           489:             then Min(d);
        !           490:             end if;
        !           491:            declare
        !           492:              t : Transfo := Rotate(d,piv);
        !           493:              tr_al : Array_of_Lists(al'first..(al'last-1));
        !           494:               degen : boolean := false;
        !           495:             begin
        !           496:               Apply(t,d);
        !           497:              for i in tr_al'range loop
        !           498:                tr_al(i) := Transform_and_Reduce(t,piv,al(i+1));
        !           499:                 Remove_Duplicates(tr_al(i));
        !           500:                 degen := (Length_Of(tr_al(i)) <= 1);
        !           501:                 exit when degen;
        !           502:               end loop;
        !           503:               Clear(t);
        !           504:               if not degen
        !           505:               then res := d(piv)*Mixed_Volume(n-1,tr_al);
        !           506:                else res := 0;
        !           507:               end if;
        !           508:               Deep_Clear(tr_al);
        !           509:             end;
        !           510:       end if;
        !           511:     end;
        !           512:     return res;
        !           513:   end Two_Terms_Mixed_Vol;
        !           514:
        !           515:   function Facet_Normal ( n : natural; facet,pts : VecVec ) return Vector is
        !           516:
        !           517:     res,pt1,pt2 : Vector(1..n);
        !           518:     im : Matrix(1..n,1..n);
        !           519:     cnt : natural := 0;
        !           520:
        !           521:   begin
        !           522:     for i in facet'range loop
        !           523:       if facet(i)'length > 1
        !           524:        then pt1 := pts(facet(i)(facet(i)'first)).all;
        !           525:             for j in facet(i)'first+1..facet(i)'last loop
        !           526:               pt2 := pts(facet(i)(j)).all;
        !           527:               cnt := cnt + 1;
        !           528:               for k in pt1'range loop
        !           529:                 im(cnt,k) := pt2(k) - pt1(k);
        !           530:               end loop;
        !           531:             end loop;
        !           532:       end if;
        !           533:     end loop;
        !           534:     for j in 1..n loop
        !           535:       im(n,j) := 0;
        !           536:     end loop;
        !           537:     Upper_Triangulate(im);
        !           538:     Scale(im);
        !           539:     res := (1..n => 0);
        !           540:     Solve0(im,res);
        !           541:     Normalize(res);
        !           542:    -- put("The facet normal : "); put(res); new_line;
        !           543:     return res;
        !           544:   end Facet_Normal;
        !           545:
        !           546:   function Minkowski_Sum ( n : natural; al : Array_of_Lists )
        !           547:                          return natural is
        !           548:
        !           549:   -- DESCRIPTION :
        !           550:   --   Computes the mixed volume of the polytope generated
        !           551:   --   by the points in al, where n > 1.
        !           552:
        !           553:     res,m,ptslen : natural;
        !           554:     vl,vl_last,al1 : List;
        !           555:     typ,ind : Vector(1..n);
        !           556:     perm,mix : Link_to_Vector;
        !           557:     wal : Array_of_Lists(al'range) := Interchange2(al);
        !           558:
        !           559:     procedure Update ( v : in Vector; i : in integer;
        !           560:                       added : in out boolean ) is
        !           561:
        !           562:     -- DESCRIPTION :
        !           563:     --   This procedure computes the support of the first list
        !           564:     --   in the direction v; if this support is not zero,
        !           565:     --   the projection will be computed.
        !           566:     --   The parameter added becomes true if v has been added to vl.
        !           567:
        !           568:       pal : Array_of_Lists(al'first..(al'last-1));
        !           569:       pv : integer;
        !           570:       degen : boolean;
        !           571:
        !           572:     begin
        !           573:       if not Is_In(vl,v)
        !           574:        then pv := Maximal_Support(al1,v);
        !           575:             if pv > 0
        !           576:              then Projection(wal,v,i,pal,degen);
        !           577:                  if not degen
        !           578:                   then declare
        !           579:                           mv : integer := Mixed_Volume(n-1,pal);
        !           580:                         begin
        !           581:                           if mv > 0
        !           582:                           then res := res + pv*mv;
        !           583:                                 Append(vl,vl_last,v);
        !           584:                                 added := true;
        !           585:                           end if;
        !           586:                         end;
        !           587:                         Deep_Clear(pal);
        !           588:                   end if;
        !           589:             end if;
        !           590:       end if;
        !           591:     end Update;
        !           592:
        !           593:     procedure Enumerate_Facets ( lpts : in Array_of_Lists; len : in natural ) is
        !           594:
        !           595:       pts : VecVec(1..len);
        !           596:       cnt : integer;
        !           597:
        !           598:       procedure Compute_Facet ( facet : in VecVec; cont : out boolean ) is
        !           599:
        !           600:         v,w : Vector(1..n);
        !           601:         i : integer;
        !           602:         added : boolean;
        !           603:
        !           604:       begin
        !           605:         v := Facet_Normal(n,facet,pts);
        !           606:         i := Pivot(v);
        !           607:         if i <= v'last
        !           608:          then added := false;
        !           609:               Update(v,i,added);
        !           610:               if not added
        !           611:               then Min(v); w := v;
        !           612:               else w := -v; added := false;
        !           613:               end if;
        !           614:              Update(w,i,added);
        !           615:         end if;
        !           616:         cont := true;
        !           617:       end Compute_Facet;
        !           618:
        !           619:       procedure Compute_Facets is new Enumerate_Faces_of_Sum(Compute_Facet);
        !           620:
        !           621:     begin
        !           622:       pts(ind(1)..ind(2)-1) := Shallow_Create(Tail_Of(al1));
        !           623:       cnt := lpts'first + mix(mix'first);
        !           624:       for i in mix'first+1..mix'last loop
        !           625:         if i < mix'last
        !           626:          then pts(ind(i)..ind(i+1)-1) := Shallow_Create(lpts(cnt));
        !           627:               cnt := cnt + mix(i);
        !           628:          else pts(ind(i)..len) := Shallow_Create(lpts(cnt));
        !           629:         end if;
        !           630:       end loop;
        !           631:       Compute_Facets(ind(mix'range),typ(mix'range),n-1,pts);
        !           632:     end Enumerate_Facets;
        !           633:
        !           634:   begin
        !           635:     m := Length_Of(wal(wal'first));
        !           636:     if m = 2
        !           637:      then return Two_Terms_Mixed_Vol(n,wal);
        !           638:      elsif m > 2
        !           639:          then
        !           640:            Mixture(al,perm,mix);
        !           641:           -- put("Type of mixture : "); put(mix); new_line;
        !           642:           -- put(" with permutation : "); put(perm); new_line;
        !           643:            wal := Permute(perm.all,al);
        !           644:            declare
        !           645:             shiftvec : Link_to_Vector;
        !           646:              nulvec : Vector(1..n) := (1..n => 0);
        !           647:             shifted : boolean;
        !           648:              cnt : integer;
        !           649:           begin
        !           650:            -- SHIFT OF THE FIRST LIST ( then all pv >= 0) :
        !           651:              if not Is_In(wal(wal'first),nulvec)
        !           652:               then shiftvec := Graded_Max(wal(wal'first));
        !           653:                   al1 := Shift(wal(wal'first),shiftvec); shifted := true;
        !           654:               else al1 := wal(wal'first);                 shifted := false;
        !           655:              end if;
        !           656:             -- ENUMERATE FACES OF SUM OF THE RIGHT TYPE :
        !           657:              Move_to_Front(al1,nulvec);
        !           658:              wal(wal'first) := al1;
        !           659:             res := 0;
        !           660:              typ(1) := mix(mix'first)-1;
        !           661:              typ(2) := mix(mix'first+1); ind(1) := 1;
        !           662:              ind(2) := ind(1) + Length_Of(al1) - 1;  -- skip null vector
        !           663:              cnt := wal'first + mix(mix'first);
        !           664:             for i in mix'first+2..mix'last loop
        !           665:                typ(i) := mix(i);
        !           666:                ind(i) := ind(i-1) + Length_Of(wal(cnt));
        !           667:                cnt := cnt + mix(i-1);
        !           668:              end loop;
        !           669:              ptslen := ind(mix'last) + Length_Of(wal(cnt)) - 1;
        !           670:              Enumerate_Facets(wal,ptslen);
        !           671:             -- CLEANING UP :
        !           672:              Deep_Clear(vl); Clear(perm); Clear(mix);
        !           673:              if shifted
        !           674:              then Clear(shiftvec);
        !           675:                    Deep_Clear(al1);
        !           676:              end if;
        !           677:              return res;
        !           678:            end;
        !           679:       else -- m < 2
        !           680:            return 0;
        !           681:     end if;
        !           682:   end Minkowski_Sum;
        !           683:
        !           684:   function Mixed_Volume ( n : natural; al : Array_of_Lists )
        !           685:                        return natural is
        !           686:   begin
        !           687:     if (n = 0) or Is_Null(al(al'first))
        !           688:      then return 0;
        !           689:      elsif n = 1
        !           690:          then declare
        !           691:                min,max : integer := 0;
        !           692:                d : Link_to_Vector := Head_Of(al(al'first));
        !           693:               begin
        !           694:                Min_Max(al(al'first),d'first,min,max);
        !           695:                return (max - min);
        !           696:               end;
        !           697:          elsif All_Equal(al)
        !           698:             then return Volume(n,al(al'first));
        !           699:             else return Minkowski_Sum(n,al);
        !           700:     end if;
        !           701:   end Mixed_Volume;
        !           702:
        !           703: -- MIXED VOLUME COMPUTATIONS WITH TREE OF USEFUL DIRECTIONS :
        !           704:
        !           705:   function Two_Terms_Mixed_Volume ( n : natural; al : Array_of_Lists;
        !           706:                                    tv : Tree_of_Vectors )
        !           707:                                  return natural is
        !           708:
        !           709:   -- DESCRIPTION :
        !           710:   --   returns the mixed volume of the polytopes generated by the
        !           711:   --   points in al, where the first polytope is generated by only
        !           712:   --   two points.
        !           713:
        !           714:     first,second : Link_to_Vector;
        !           715:     l : List renames al(al'first);
        !           716:     res : natural;
        !           717:
        !           718:   begin
        !           719:     first := Head_Of(l);
        !           720:     second := Head_Of(Tail_Of(l));
        !           721:     declare
        !           722:       d : Vector(first'range);
        !           723:       piv : integer := 0;
        !           724:     begin
        !           725:       for i in d'range loop
        !           726:        d(i) := first(i) - second(i);
        !           727:        if (piv = 0) and then (d(i) /= 0)
        !           728:         then piv := i;
        !           729:         end if;
        !           730:       end loop;
        !           731:       if piv = 0
        !           732:        then return 0;
        !           733:        else if d(piv) < 0
        !           734:             then Min(d);
        !           735:             end if;
        !           736:            declare
        !           737:              t : Transfo := Rotate(d,piv);
        !           738:              tr_al : Array_of_Lists(al'first..(al'last-1));
        !           739:               degen : boolean := false;
        !           740:             begin
        !           741:               Apply(t,d);
        !           742:              for i in tr_al'range loop
        !           743:                tr_al(i) := Transform_and_Reduce(t,piv,al(i+1));
        !           744:                 Remove_Duplicates(tr_al(i));
        !           745:                 degen := (Length_Of(tr_al(i)) <= 1);
        !           746:                 exit when degen;
        !           747:               end loop;
        !           748:               Clear(t);
        !           749:               if not degen
        !           750:               then res := d(piv)*Mixed_Volume(n-1,tr_al,tv);
        !           751:                else res := 0;
        !           752:               end if;
        !           753:               Deep_Clear(tr_al);
        !           754:             end;
        !           755:       end if;
        !           756:     end;
        !           757:     return res;
        !           758:   end Two_Terms_Mixed_Volume;
        !           759:
        !           760:   function Minkowski_Sum ( n : natural; al : Array_of_Lists;
        !           761:                            tv : Tree_of_Vectors ) return natural is
        !           762:
        !           763:   -- DESCRIPTION :
        !           764:   --   Computes the mixed volume of the polytope generated
        !           765:   --   by the points in al, where n > 1.
        !           766:   --   The tree of degrees is not empty.
        !           767:
        !           768:     res,m : natural;
        !           769:     al1 : List;
        !           770:     wal : Array_of_Lists(al'range) := Interchange2(al);
        !           771:     tmp : Tree_of_Vectors;
        !           772:     perm,mix : Link_to_Vector;
        !           773:
        !           774:   begin
        !           775:     m := Length_Of(wal(wal'first));
        !           776:     if m = 2
        !           777:      then return Two_Terms_Mixed_Volume(n,wal,tv);
        !           778:      elsif m > 2
        !           779:          then
        !           780:            Mixture(al,perm,mix);
        !           781:            wal := Permute(perm.all,al);
        !           782:            declare
        !           783:             shiftvec : Link_to_Vector;
        !           784:              nulvec : Vector(1..n) := (1..n => 0);
        !           785:             shifted : boolean;
        !           786:            begin
        !           787:             -- SHIFT OF THE FIRST LIST ( then all pv >= 0) :
        !           788:              if not Is_In(wal(wal'first),nulvec)
        !           789:               then shiftvec := Graded_Max(wal(wal'first));
        !           790:                   al1 := Shift(wal(wal'first),shiftvec); shifted := true;
        !           791:               else al1 := wal(wal'first);                 shifted := false;
        !           792:              end if;
        !           793:              Move_to_Front(al1,nulvec);
        !           794:              wal(wal'first) := al1;
        !           795:            -- COMPUTING THE MIXED VOLUME :
        !           796:              tmp := tv;  res := 0;
        !           797:             while not Is_Null(tmp) loop
        !           798:               declare
        !           799:                 nd : node := Head_Of(tmp);
        !           800:                 v : Link_to_Vector := nd.d;
        !           801:                 i : integer := Pivot(v);
        !           802:                 pv : integer := Maximal_Support(al1,v.all);
        !           803:                 pal : Array_of_Lists(al'first..(al'last-1));
        !           804:                 degen : boolean;
        !           805:                begin
        !           806:                 Projection(wal,v.all,i,pal,degen);
        !           807:                 if (nd.ltv = null) or else Is_Null(nd.ltv.all)
        !           808:                   then res := res + pv*Mixed_Volume(n-1,pal);
        !           809:                   else res := res + pv*Mixed_Volume(n-1,pal,nd.ltv.all);
        !           810:                  end if;
        !           811:                  Deep_Clear(pal);
        !           812:                end;
        !           813:                tmp := Tail_Of(tmp);
        !           814:              end loop;
        !           815:             -- CLEANING UP :
        !           816:              Clear(perm); Clear(mix);
        !           817:              if shifted
        !           818:              then Clear(shiftvec); Deep_Clear(al1);
        !           819:              end if;
        !           820:              return res;
        !           821:            end;
        !           822:          else -- m < 2
        !           823:            return 0;
        !           824:     end if;
        !           825:   end Minkowski_Sum;
        !           826:
        !           827:   function Mixed_Volume ( n : natural; al : Array_of_Lists;
        !           828:                          tv : Tree_of_Vectors ) return natural is
        !           829:   begin
        !           830:     if (n = 0) or Is_Null(al(al'first))
        !           831:      then return 0;
        !           832:      elsif n = 1
        !           833:          then declare
        !           834:                min,max : integer := 0;
        !           835:                d : Link_to_Vector := Head_Of(al(al'first));
        !           836:               begin
        !           837:                Min_Max(al(al'first),d'first,min,max);
        !           838:                return (max - min);
        !           839:               end;
        !           840:          elsif All_Equal(al)
        !           841:             then return Volume(n,al(al'first),tv);
        !           842:             elsif not Is_Null(tv)
        !           843:                 then return Minkowski_Sum(n,al,tv);
        !           844:                 else return Minkowski_Sum(n,al);
        !           845:     end if;
        !           846:   end Mixed_Volume;
        !           847:
        !           848: -- MIXED VOLUME COMPUTATIONS WITH CREATION OF TREE OF USEFUL DIRECTIONS :
        !           849:
        !           850:   procedure Two_Terms_Mixed_Vol
        !           851:              ( n : in natural; al : in Array_of_Lists;
        !           852:               tv : in out Tree_of_Vectors; mv : out natural ) is
        !           853:
        !           854:   -- DESCRIPTION :
        !           855:   --   returns the mixed volume of the polytopes generated by the
        !           856:   --   points in al, where the first polytope is generated by only
        !           857:   --   two points.
        !           858:
        !           859:     first,second : Link_to_Vector;
        !           860:     l : List renames al(al'first);
        !           861:
        !           862:   begin
        !           863:     first := Head_Of(l);
        !           864:     second := Head_Of(Tail_Of(l));
        !           865:     declare
        !           866:       d : Vector(first'range);
        !           867:       piv : integer := 0;
        !           868:     begin
        !           869:       for i in d'range loop
        !           870:        d(i) := first(i) - second(i);
        !           871:        if (piv = 0) and then (d(i) /= 0)
        !           872:         then piv := i;
        !           873:         end if;
        !           874:       end loop;
        !           875:       if piv = 0
        !           876:        then mv := 0;
        !           877:        else if d(piv) < 0
        !           878:             then Min(d);
        !           879:             end if;
        !           880:            declare
        !           881:              t : Transfo := Rotate(d,piv);
        !           882:              tr_al : Array_of_Lists(al'first..(al'last-1));
        !           883:              mvl : natural;
        !           884:               degen : boolean := false;
        !           885:             begin
        !           886:               Apply(t,d);
        !           887:              for i in tr_al'range loop
        !           888:                tr_al(i) := Transform_and_Reduce(t,piv,al(i+1));
        !           889:                 Remove_Duplicates(tr_al(i));
        !           890:                 degen := (Length_Of(tr_al(i)) <= 1);
        !           891:                 exit when degen;
        !           892:               end loop;
        !           893:               Clear(t);
        !           894:               if not degen
        !           895:               then Mixed_Volume(n-1,tr_al,tv,mvl); mv := d(piv)*mvl;
        !           896:                else mv := 0;
        !           897:               end if;
        !           898:               Deep_Clear(tr_al);
        !           899:             end;
        !           900:       end if;
        !           901:     end;
        !           902:   end Two_Terms_Mixed_Vol;
        !           903:
        !           904:   procedure Minkowski_Sum ( n : in natural; al : in Array_of_Lists;
        !           905:                             tv : in out Tree_of_Vectors; mv : out natural ) is
        !           906:
        !           907:   -- DESCRIPTION :
        !           908:   --   Computes the mixed volume of the polytope generated
        !           909:   --   by the points in al, where n > 1.
        !           910:
        !           911:     res,m,ptslen : natural;
        !           912:     al1 : List;
        !           913:     typ,ind : Vector(1..n);
        !           914:     perm,mix : Link_to_Vector;
        !           915:     wal : Array_of_Lists(al'range) := Interchange2(al);
        !           916:
        !           917:     procedure Update ( v : in Vector; i : in integer;
        !           918:                       added : in out boolean ) is
        !           919:
        !           920:     -- DESCRIPTION :
        !           921:     --   This procedure computes the support of the first list
        !           922:     --   in the direction v; if this support is not zero,
        !           923:     --   the projection will be computed.
        !           924:     --   The parameter added becomes true if v has been added to vl.
        !           925:
        !           926:       pal : Array_of_Lists(al'first..(al'last-1));
        !           927:       pv : integer;
        !           928:       degen : boolean;
        !           929:
        !           930:     begin
        !           931:       if not Is_In(tv,v)
        !           932:        then pv := Maximal_Support(al1,v);
        !           933:             if pv > 0
        !           934:              then Projection(wal,v,i,pal,degen);
        !           935:                   if not degen
        !           936:                    then declare
        !           937:                           tmp : Tree_of_Vectors;
        !           938:                           mv : natural;
        !           939:                         begin
        !           940:                           Mixed_Volume(n-1,pal,tmp,mv);
        !           941:                           if mv = 0
        !           942:                            then Clear(tmp);
        !           943:                            else res := res + pv*mv;
        !           944:                                 declare
        !           945:                                   nd : node;
        !           946:                                 begin
        !           947:                                   nd.d := new Vector'(v);
        !           948:                                   if not Is_Null(tmp)
        !           949:                                    then nd.ltv := new Tree_of_Vectors'(tmp);
        !           950:                                   end if;
        !           951:                                   Construct(nd,tv);
        !           952:                                 end;
        !           953:                                 added := true;
        !           954:                           end if;
        !           955:                         end;
        !           956:                         Deep_Clear(pal);
        !           957:                   end if;
        !           958:             end if;
        !           959:       end if;
        !           960:     end Update;
        !           961:
        !           962:     procedure Enumerate_Facets ( lpts : in Array_of_Lists; len : in natural ) is
        !           963:
        !           964:       pts : VecVec(1..len);
        !           965:       cnt : integer;
        !           966:
        !           967:       procedure Compute_Facet ( facet : in VecVec; cont : out boolean ) is
        !           968:
        !           969:         v,w : Vector(1..n);
        !           970:         i : integer;
        !           971:         added : boolean;
        !           972:       begin
        !           973:         v := Facet_Normal(n,facet,pts);
        !           974:         i := Pivot(v);
        !           975:         if i <= v'last
        !           976:          then added := false;
        !           977:               Update(v,i,added);
        !           978:               if not added
        !           979:                then Min(v); w := v;
        !           980:                else w := -v; added := false;
        !           981:               end if;
        !           982:               Update(w,i,added);
        !           983:         end if;
        !           984:         cont := true;
        !           985:       end Compute_Facet;
        !           986:
        !           987:       procedure Compute_Facets is
        !           988:         new Enumerate_Faces_of_Sum(Compute_Facet);
        !           989:
        !           990:     begin
        !           991:       pts(ind(1)..ind(2)-1) := Shallow_Create(Tail_Of(al1));
        !           992:       cnt := lpts'first + mix(mix'first);
        !           993:       for i in mix'first+1..mix'last loop
        !           994:         if i < mix'last
        !           995:          then pts(ind(i)..ind(i+1)-1) := Shallow_Create(lpts(cnt));
        !           996:               cnt := cnt + mix(i);
        !           997:          else pts(ind(i)..len) := Shallow_Create(lpts(cnt));
        !           998:         end if;
        !           999:       end loop;
        !          1000:       Compute_Facets(ind(mix'range),typ(mix'range),n-1,pts);
        !          1001:     end Enumerate_Facets;
        !          1002:
        !          1003:   begin
        !          1004:     m := Length_Of(wal(wal'first));
        !          1005:     if m = 2
        !          1006:      then Two_Terms_Mixed_Vol(n,wal,tv,mv);
        !          1007:      elsif m > 2
        !          1008:          then
        !          1009:            Mixture(al,perm,mix);
        !          1010:            wal := Permute(perm.all,al);
        !          1011:            declare
        !          1012:             shiftvec : Link_to_Vector;
        !          1013:              nulvec : Vector(1..n) := (1..n => 0);
        !          1014:              shifted : boolean;
        !          1015:              cnt : integer;
        !          1016:            begin
        !          1017:             -- SHIFT OF THE FIRST LIST ( then all pv >= 0) :
        !          1018:              if not Is_In(wal(wal'first),nulvec)
        !          1019:               then shiftvec := Graded_Max(wal(wal'first));
        !          1020:                    al1 := Shift(wal(wal'first),shiftvec); shifted := true;
        !          1021:               else al1 := wal(wal'first);                 shifted := false;
        !          1022:              end if;
        !          1023:             -- ENUMERATE FACES OF SUM OF THE RIGHT TYPE :
        !          1024:              Move_to_Front(al1,nulvec);
        !          1025:              wal(wal'first) := al1;
        !          1026:              res := 0;
        !          1027:              typ(1) := mix(mix'first)-1;
        !          1028:              typ(2) := mix(mix'first+1); ind(1) := 1;
        !          1029:              ind(2) := ind(1) + Length_Of(al1) - 1;  -- skip null vector
        !          1030:              cnt := wal'first + mix(mix'first);
        !          1031:              for i in mix'first+2..mix'last loop
        !          1032:                typ(i) := mix(i);
        !          1033:                ind(i) := ind(i-1) + Length_Of(wal(cnt));
        !          1034:                cnt := cnt + mix(i-1);
        !          1035:              end loop;
        !          1036:              ptslen := ind(mix'last) + Length_Of(wal(cnt)) - 1;
        !          1037:              Enumerate_Facets(wal,ptslen);
        !          1038:             -- CLEANING UP :
        !          1039:              Clear(perm); Clear(mix);
        !          1040:              if shifted
        !          1041:               then Clear(shiftvec); Deep_Clear(al1);
        !          1042:              end if;
        !          1043:              mv := res;
        !          1044:            end;
        !          1045:          else -- m < 2
        !          1046:            mv := 0;
        !          1047:     end if;
        !          1048:   end Minkowski_Sum;
        !          1049:
        !          1050:   procedure Mixed_Volume ( n : in natural; al : in Array_of_Lists;
        !          1051:                           tv : in out Tree_of_Vectors; mv : out natural ) is
        !          1052:   begin
        !          1053:     if (n = 0) or Is_Null(al(al'first))
        !          1054:      then mv := 0;
        !          1055:      elsif n = 1
        !          1056:          then declare
        !          1057:                min,max : integer := 0;
        !          1058:                d : Link_to_Vector := Head_Of(al(al'first));
        !          1059:               begin
        !          1060:                Min_Max(al(al'first),d'first,min,max);
        !          1061:                mv := max - min;
        !          1062:               end;
        !          1063:          elsif All_Equal(al)
        !          1064:             then Volume(n,al(al'first),tv,mv);
        !          1065:             else Minkowski_Sum(n,al,tv,mv);
        !          1066:     end if;
        !          1067:   end Mixed_Volume;
        !          1068:
        !          1069: end Volumes;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>