Annotation of OpenXM_contrib/PHC/Ada/Root_Counts/Implift/volumes.adb, Revision 1.1.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>