Annotation of OpenXM_contrib/PHC/Ada/Root_Counts/Implift/vertices.adb, Revision 1.1.1.1
1.1 maekawa 1: with Standard_Floating_Numbers; use Standard_Floating_Numbers;
2: with Standard_Integer_VecVecs; use Standard_Integer_VecVecs;
3: with Standard_Floating_Matrices; use Standard_Floating_Matrices;
4: with Dictionaries;
5: with Linear_Programming; use Linear_Programming;
6: with Integer_Face_Enumerators; use Integer_Face_Enumerators;
7:
8: with Integer_Vectors_Utilities; use Integer_Vectors_Utilities;
9: with Lists_of_Vectors_Utilities; use Lists_of_Vectors_Utilities;
10: with Transformations; use Transformations;
11: with Transforming_Integer_Vector_Lists; use Transforming_Integer_Vector_Lists;
12:
13: package body Vertices is
14:
15: function Is_In_Hull ( point : Standard_Integer_Vectors.Vector; l : List )
16: return boolean is
17:
18: fpt : Standard_Floating_Vectors.Vector(point'range);
19:
20: begin
21: for i in point'range loop
22: fpt(i) := double_float(point(i));
23: end loop;
24: return Is_In_Hull(fpt,l);
25: end Is_In_Hull;
26:
27: function Is_In_Hull ( point : Standard_Floating_Vectors.Vector; l : List )
28: return boolean is
29:
30: -- ALGORITHM:
31: -- The following linear program will be solved:
32: --
33: -- min u_0 + u_1 + .. + u_n
34: --
35: -- l_1*p_1i + l_2*p_2i + .. + l_m*p_mi + u_i*q_i = q_i i=1,2,..,n
36: --
37: -- l_1 + l_2 + .. + l_m + u_0 = 1
38: --
39: -- to determine whether q belongs to the convex hull spanned by the
40: -- vectors p_1,p_2,..,p_m.
41: -- If all u_i are zero and all constraints are satisfied,
42: -- then q belongs to the convex hull.
43:
44: -- CONSTANTS :
45:
46: n : constant natural := point'last;
47: m : constant natural := 2*n+2; -- number of constraints
48: nb : constant natural := Length_Of(l)+n+1; -- number of unknowns
49: eps : constant double_float := 10.0**(-10);
50:
51: -- VARIABLES :
52:
53: dic : matrix(0..m,0..nb);
54: sol : Standard_Floating_Vectors.vector(1..nb);
55: inbas : Standard_Integer_Vectors.Vector(1..m) := (1..m => 0);
56: outbas : Standard_Integer_Vectors.Vector(1..nb) := (1..nb => 0);
57: nit : natural := 0;
58: feasi : boolean;
59:
60: tmp : List;
61: pt : Link_to_Vector;
62: s : double_float;
63:
64: begin
65:
66: -- INITIALIZATION OF target :
67:
68: for i in 0..(nb-n-1) loop
69: dic(0,i) := 0.0; -- sum of the lambda's
70: end loop;
71: for i in (nb-n)..nb loop
72: dic(0,i) := -1.0; -- sum of the mu's
73: end loop;
74:
75: -- INITIALIZATION OF dic :
76:
77: for i in 0..(nb-n) loop
78: dic(m-1,i) := 1.0; -- sum of the lambda's + mu_0
79: dic(m,i) := -1.0;
80: end loop;
81: for i in (nb-n+1)..nb loop
82: dic(m-1,i) := 0.0;
83: dic(m,i) := 0.0;
84: end loop;
85: for i in 1..n loop
86: for j in (nb-n)..nb loop
87: if i /= j-nb+n
88: then dic(i,j) := 0.0;
89: dic(i+n,j) := 0.0;
90: end if;
91: end loop;
92: end loop;
93:
94: tmp := l;
95: for j in 1..(nb-n-1) loop
96: pt := Head_Of(tmp);
97: for i in pt'range loop
98: dic(i,j) := double_float(pt(i));
99: dic(i+n,j) := -double_float(pt(i));
100: end loop;
101: tmp := Tail_Of(tmp);
102: end loop;
103:
104: for i in point'range loop
105: dic(i,0) := point(i);
106: dic(i+n,0) := -point(i);
107: dic(i,i+nb-n) := point(i);
108: dic(i+n,i+nb-n) := -point(i);
109: end loop;
110:
111: -- SOLVE THE LINEAR PROGRAM :
112:
113: Dictionaries.Init_Basis(inbas,outbas);
114: Dual_Simplex(dic,eps,inbas,outbas,nit,feasi);
115: if not feasi
116: then return false;
117: else
118: sol := Dictionaries.Primal_Solution(dic,inbas,outbas);
119:
120: -- CHECK THE SOLUTION :
121:
122: s := 0.0;
123: for i in 1..(nb-n-1) loop
124: s := s + sol(i);
125: end loop;
126: if abs(s - 1.0) > eps
127: then return false;
128: end if;
129: s := 0.0;
130: for i in (nb-n)..nb loop
131: s := s + sol(i);
132: end loop;
133: if abs(s) > eps
134: then return false;
135: end if;
136:
137: return true;
138:
139: end if;
140:
141: end Is_In_Hull;
142:
143: function Vertex_Points ( l : List ) return List is
144:
145: result,result_last : List;
146: tmp,rest,origrest,rest_last : List;
147: pt : Link_to_Vector;
148:
149: begin
150: if Is_Null(l) or else Is_Null(Tail_Of(l))
151: then return l;
152: else Copy(Tail_Of(l),rest);
153: origrest := rest;
154: rest_last := rest;
155: while not Is_Null(Tail_Of(rest_last)) loop
156: rest_last := Tail_Of(rest_last);
157: end loop;
158: tmp := l;
159: for i in 1..Length_Of(l) loop
160: pt := Head_Of(tmp);
161: if not Is_In_Hull(pt.all,rest)
162: then Append(result,result_last,pt.all);
163: Append(rest,rest_last,pt.all);
164: end if;
165: rest := Tail_Of(rest);
166: tmp := Tail_Of(tmp);
167: end loop;
168: Clear(origrest);
169: return result;
170: end if;
171: end Vertex_Points;
172:
173: function Vertex_Points1 ( l : List ) return List is
174:
175: len : constant natural := Length_Of(l);
176: pts : VecVec(1..len) := Shallow_Create(l);
177: result,result_last : List;
178:
179: procedure Collect_Vertex ( i : in integer; cont : out boolean ) is
180: begin
181: Append(result,result_last,pts(i).all);
182: cont := true;
183: end Collect_Vertex;
184: procedure Enum_Vertices is new Enumerate_Vertices(Collect_Vertex);
185:
186: begin
187: Enum_Vertices(pts);
188: return result;
189: end Vertex_Points1;
190:
191: procedure Add ( pt : Link_to_Vector; l : in out List ) is
192:
193: -- DESCRIPTION :
194: -- Constructs the point to the list, but without sharing.
195:
196: newpt : Link_to_Vector := new Vector'(pt.all);
197:
198: begin
199: Construct(newpt,l);
200: end Add;
201:
202: function Extremal_Points ( l : List; v : Link_to_Vector ) return List is
203:
204: min,max,sp : integer;
205: tmp,res : List;
206: minpt,maxpt,pt : Link_to_Vector;
207:
208: begin
209: if Length_Of(l) <= 1
210: then Copy(l,res);
211: else pt := Head_Of(l);
212: min := pt*v; max := min;
213: minpt := pt; maxpt := pt;
214: tmp := Tail_Of(l);
215: while not Is_Null(tmp) loop
216: pt := Head_Of(tmp);
217: sp := pt*v;
218: if sp > max
219: then max := sp; maxpt := pt;
220: elsif sp < min
221: then min := sp; minpt := pt;
222: end if;
223: tmp := Tail_Of(tmp);
224: end loop;
225: Add(minpt,res);
226: if min /= max
227: then Add(maxpt,res);
228: end if;
229: end if;
230: return res;
231: end Extremal_Points;
232:
233: function Extremal_Points ( k,n : natural; exl,l : List ) return List is
234:
235: res,tmp,nres : List;
236: iv : VecVec(1..k);
237: v : Link_to_Vector := new Vector(1..n);
238: sp : integer;
239: pt : Link_to_Vector;
240: done : boolean;
241:
242: begin
243: tmp := exl;
244: for j in iv'range loop
245: iv(j) := Head_Of(tmp);
246: tmp := Tail_Of(tmp);
247: end loop;
248: v := Compute_Normal(iv);
249: sp := Head_Of(exl)*v;
250: nres := Extremal_Points(l,v);
251: tmp := nres;
252: res := exl;
253: done := false;
254: while not done and not Is_Null(tmp) loop
255: pt := Head_Of(tmp);
256: if pt*v /= sp
257: then Add(pt,res);
258: done := true;
259: else tmp := Tail_Of(tmp);
260: end if;
261: end loop;
262: Clear(v);
263: return res;
264: end Extremal_Points;
265:
266: function Max_Extremal_Points ( k,n : natural; exl,l : List ) return List is
267:
268: res,tmp,nres : List;
269: iv : VecVec(1..k);
270: v : Link_to_Vector := new Vector(1..n);
271: sp : integer;
272: pt : Link_to_Vector;
273: done : boolean;
274:
275: begin
276: tmp := exl;
277: for j in iv'range loop
278: iv(j) := Head_Of(tmp);
279: tmp := Tail_Of(tmp);
280: end loop;
281: v := Compute_Normal(iv);
282: sp := Head_Of(exl)*v;
283: nres := Extremal_Points(l,v);
284: --put("The computed normal : "); put(v); new_line;
285: --put("The inner product : "); put(sp,1); new_line;
286: --put_line("The list of extremal points :"); put(nres);
287: tmp := nres;
288: Copy(exl,res);
289: done := false;
290: while not done and not Is_Null(tmp) loop
291: pt := Head_Of(tmp);
292: if pt*v /= sp
293: then Add(pt,res);
294: done := true;
295: else tmp := Tail_Of(tmp);
296: end if;
297: end loop;
298: Clear(nres);
299: if not done
300: then -- for all points x in l : <x,v> = sp
301: if n >= 2
302: then declare
303: i : integer := Pivot(v);
304: t,invt : Transfo;
305: texl,tl,tres : List;
306: begin
307: if i <= v'last
308: then t := Build_Transfo(v,i);
309: invt := Invert(t);
310: texl := Transform_and_Reduce(t,i,exl);
311: tl := Transform_and_Reduce(t,i,l);
312: tres := Max_Extremal_Points(k,n-1,texl,tl);
313: --put("The normal : "); put(v); new_line;
314: --put_line("The list of points : "); put(l);
315: --put_line("The list of extremal points :"); put(exl);
316: --put_line("The transformed list of points : "); put(tl);
317: --put_line("The transformed list of extremal points : ");
318: --put(texl);
319: --put_line("The computed transformed extremal points : ");
320: --put(tres);
321: --put("k : "); put(k,1); new_line;
322: Clear(t); Clear(texl); Clear(tl);
323: if Length_Of(tres) = k+1
324: then res := Insert_and_Transform(tres,i,sp,invt);
325: else Copy(exl,res);
326: end if;
327: --put_line("The computed extremal points : "); put(res);
328: Clear(tres); --responsible for segmentation violation...
329: Clear(invt);
330: else Copy(exl,res);
331: end if;
332: end;
333: else Copy(exl,res);
334: end if;
335: end if;
336: Clear(v);
337: --put_line("The new list of extremal points : "); put(res);
338: return res;
339: end Max_Extremal_Points;
340:
341: function Extremal_Points ( n : natural; l : List ) return List is
342:
343: res : List;
344: nor : Link_to_Vector := new Vector'(1..n => 1);
345: k : natural;
346:
347: begin
348: res := Extremal_Points(l,nor);
349: Clear(nor);
350: if Length_Of(res) < 2
351: then return res;
352: else k := 2;
353: while k < n+1 loop
354: res := Extremal_Points(k,n,res,l);
355: exit when Length_Of(res) = k;
356: k := k+1;
357: end loop;
358: return res;
359: end if;
360: end Extremal_Points;
361:
362: function Two_Extremal_Points ( n : natural; l : List ) return List is
363:
364: -- DESCRIPTION :
365: -- Computes two extremal points of the list l.
366:
367: res,tmp : List;
368: pt,minpt,maxpt : Link_to_Vector;
369: min,max : integer;
370:
371: begin
372: if Length_Of(l) <= 2
373: then Copy(l,res);
374: else for i in 1..n loop
375: pt := Head_Of(l);
376: max := pt(i); min := max;
377: maxpt := pt; minpt := pt;
378: tmp := Tail_Of(l);
379: while not Is_Null(tmp) loop
380: pt := Head_Of(tmp);
381: if pt(i) < min
382: then min := pt(i); minpt := pt;
383: elsif pt(i) > max
384: then max := pt(i); maxpt := pt;
385: end if;
386: tmp := Tail_Of(tmp);
387: end loop;
388: if Is_Null(res)
389: then Add(minpt,res);
390: if min /= max
391: then Add(maxpt,res);
392: end if;
393: else pt := Head_Of(res);
394: if pt.all /= minpt.all
395: then Add(minpt,res);
396: elsif pt.all /= maxpt.all
397: then Add(maxpt,res);
398: end if;
399: end if;
400: exit when (Length_Of(res) = 2);
401: end loop;
402: end if;
403: return res;
404: end Two_Extremal_Points;
405:
406: function Max_Extremal_Points ( n : natural; l : List ) return List is
407:
408: res,wl,wres,newres : List;
409: k : natural;
410: nullvec,shiftvec : Link_to_Vector;
411: -- shifted : boolean;
412:
413: begin
414: if Length_Of(l) <= 2
415: then Copy(l,res);
416: else res := Two_Extremal_Points(n,l);
417: k := Length_Of(res);
418: if k = 2
419: then --nullvec := new Vector'(1..n => 0);
420: --if Is_In(nullvec,res)
421: -- then Copy(l,wl);
422: -- Copy(res,wres);
423: -- shifted := false;
424: -- else shiftvec := Head_Of(res);
425: -- wl := Shift(shiftvec,l);
426: -- wres := Shift(shiftvec,res);
427: -- shifted := true;
428: --end if;
429: --Clear(nullvec);
430: Copy(res,wres);
431: while k < n+1 loop
432: newres := Max_Extremal_Points(k,n,wres,l);
433: Copy(newres,wres);
434: exit when Length_Of(wres) = k;
435: k := k+1;
436: end loop;
437: res := wres;
438: -- Clear(res);
439: -- if shifted
440: -- then Min_Vector(shiftvec);
441: -- res := Shift(shiftvec,wres);
442: -- Clear(wres);
443: -- else Copy(wres,res);
444: -- end if;
445: -- Clear(wl);
446: end if;
447: end if;
448: return res;
449: end Max_Extremal_Points;
450:
451: end Vertices;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>