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>