Annotation of OpenXM_contrib/PHC/Ada/Root_Counts/Dynlift/triangulations.adb, Revision 1.1.1.1
1.1 maekawa 1: with Lists_of_Integer_Vectors; use Lists_of_Integer_Vectors;
2: with Standard_Random_Numbers; use Standard_Random_Numbers;
3:
4: --with text_io,Simplices_io; use text_io,Simplices_io;
5: --with Integer_Vectors_io; use Integer_Vectors_io;
6: --with integer_io; use integer_io;
7:
8: package body Triangulations is
9:
10: -- AUXILIAIRY HASH TABLE FOR Update_One :
11:
12: type Matrix_of_Triangulations
13: is array ( integer range <>, integer range <> ) of Triangulation;
14:
15: type Hash_Table ( n : natural ) is
16: record
17: weight1,weight2 : Link_to_Vector;
18: data : Matrix_of_Triangulations(0..n,0..n);
19: end record;
20:
21: procedure Init ( ht : in out Hash_Table; first,last : in integer ) is
22:
23: -- Initializes the hash table with Null_Triangulation.
24: -- Determines the weights for the hash function.
25: -- The numbers first and last determine the length of the weight function.
26:
27: begin
28: ht.weight1 := new Vector(first..last);
29: ht.weight2 := new Vector(first..last);
30: for i in first..last loop
31: ht.weight1(i) := Random(-last,last);
32: ht.weight2(i) := Random(-last,last);
33: end loop;
34: ht.weight1(last) := 1; -- TO AVOID PROBLEMS WITH HIGH LIFTING
35: ht.weight2(last) := 1;
36: for i in ht.data'range(1) loop
37: for j in ht.data'range(2) loop
38: ht.data(i,j) := Null_Triangulation;
39: end loop;
40: end loop;
41: end Init;
42:
43: procedure Hash_Function ( ht : in Hash_Table; s : in Simplex;
44: i,j : out integer ) is
45:
46: -- DESCRIPTION :
47: -- Computes the entries in the hash table for the simplex s.
48:
49: r1 : constant integer := ht.weight1.all*Vertex(s,1);
50: r2 : constant integer := ht.weight2.all*Vertex(s,2);
51:
52: begin
53: i := r1 mod (ht.n + 1);
54: j := r2 mod (ht.n + 1);
55: end Hash_Function;
56:
57: procedure Update ( ht : in out Hash_Table; s : in Simplex ) is
58:
59: -- DESCRIPTION :
60: -- Updates the hash table with the given simplex s.
61:
62: i,j : integer;
63:
64: begin
65: Hash_Function(ht,s,i,j);
66: Construct(s,ht.data(i,j));
67: end Update;
68:
69: function Is_In ( ht : Hash_Table; s : Simplex ) return boolean is
70:
71: -- DESCRIPTION :
72: -- Checks whether the simplex belongs to the hash table.
73:
74: i,j : integer;
75:
76: begin
77: Hash_Function(ht,s,i,j);
78: return Is_In(ht.data(i,j),s);
79: end Is_In;
80:
81: -- procedure Write_Distribution ( ht : in Hash_Table ) is
82: --
83: -- -- DESCRIPTION :
84: -- -- Writes the lengths of the lists in ht.
85: --
86: -- begin
87: -- for i in ht.data'range(1) loop
88: -- for j in ht.data'range(2) loop
89: -- put(Length_Of(ht.data(i,j)),1); put(' ');
90: -- end loop;
91: -- new_line;
92: -- end loop;
93: -- end Write_Distribution;
94:
95: procedure Clear ( ht : in out Hash_Table ) is
96:
97: -- DESCRIPTION :
98: -- Clears the allocated memory space for the hash table,
99: -- only a shallow copy is performed.
100:
101: begin
102: Clear(ht.weight1);
103: Clear(ht.weight2);
104: for i in ht.data'range(1) loop
105: for j in ht.data'range(2) loop
106: Lists_of_Simplices.Clear(Lists_of_Simplices.List(ht.data(i,j)));
107: end loop;
108: end loop;
109: end Clear;
110:
111: -- CREATORS :
112:
113: function Create ( s : Simplex ) return Triangulation is
114:
115: res : Triangulation;
116:
117: begin
118: Construct(s,res);
119: return res;
120: end Create;
121:
122: function Is_Inner ( n : natural; s : Simplex ) return boolean is
123: begin
124: for k in 1..n loop
125: if Neighbor(s,k) = Null_Simplex
126: then return false;
127: end if;
128: end loop;
129: return true;
130: end Is_Inner;
131:
132: procedure Update ( t : in out Triangulation; s : in out Simplex;
133: x : in Link_to_Vector ) is
134:
135: pos : vector(0..x'last) := Position(s,x.all);
136:
137: begin
138: for k in x'range loop
139: if Neighbor(s,k) = Null_Simplex
140: then if pos(k-1)*pos(pos'last) > 0
141: then Update(s,x,k);
142: Construct(Neighbor(s,k),t);
143: end if;
144: end if;
145: end loop;
146: end Update;
147:
148: procedure Connect_and_Update
149: ( s : in out Simplex; t : in out Triangulation ) is
150:
151: -- DESCRIPTION :
152: -- Connects the simplex with each other simplex in the triangulation
153: -- and adds it to the list t.
154:
155: tmp : Triangulation := t;
156:
157: begin
158: while not Is_Null(tmp) loop
159: declare
160: s2 : Simplex := Head_Of(tmp);
161: begin
162: Connect(s,s2);
163: --Set_Head(tmp,s2);
164: end;
165: tmp := Tail_Of(tmp);
166: end loop;
167: Construct(s,t);
168: end Connect_and_Update;
169:
170: procedure Connect_and_Update
171: ( t1 : in Triangulation; t2 : in out Triangulation ) is
172:
173: -- DESCRIPTION :
174: -- Connects all simplices in t1 properly with each other
175: -- and adds them to the list t2.
176:
177: tmp1 : Triangulation := t1;
178: tmp2 : Triangulation;
179: s1,s2 : Simplex;
180:
181: begin
182: while not Is_Null(tmp1) loop
183: s1 := Head_Of(tmp1);
184: tmp2 := Tail_Of(tmp1);
185: while not Is_Null(tmp2) loop
186: s2 := Head_Of(tmp2);
187: Connect(s1,s2);
188: tmp2 := Tail_Of(tmp2);
189: end loop;
190: tmp1 := Tail_Of(tmp1);
191: Construct(s1,t2);
192: end loop;
193: end Connect_and_Update;
194:
195: procedure Update ( t : in out Triangulation; x : in Link_to_Vector;
196: newt : out Triangulation ) is
197:
198: tmp : Triangulation := t;
199: s : Simplex;
200: nwt : Triangulation; -- for the new simplices that will contain x
201:
202: begin
203: while not Is_Null(tmp) loop
204: s := Head_Of(tmp);
205: if not Is_Inner(x'last,s)
206: then Update(nwt,s,x);
207: end if;
208: tmp := Tail_Of(tmp);
209: end loop;
210: Connect_and_Update(nwt,t);
211: newt := nwt;
212: end Update;
213:
214: procedure Update ( t : in out Triangulation; x : in Link_to_Vector ) is
215:
216: nwt : Triangulation; -- for the new simplices that will contain x
217:
218: begin
219: Update(t,x,nwt);
220: -- SHALLOW CLEAR :
221: Lists_of_Simplices.Clear(Lists_of_Simplices.List(nwt));
222: end Update;
223:
224: procedure Collect_Vertices
225: ( s : in Simplex; l : in out List ) is
226:
227: -- DESCRIPTION :
228: -- Collects the vertices in s and puts them in the list l.
229: -- Auxiliary routine for Update_One.
230:
231: pts : constant VecVec := Vertices(s);
232:
233: begin
234: for k in pts'range loop
235: if not Is_In(l,pts(k).all)
236: then declare
237: newpt : Link_to_Vector := new Vector'(pts(k).all);
238: begin
239: Construct(newpt,l);
240: end;
241: end if;
242: end loop;
243: end Collect_Vertices;
244:
245: function Has_Vertices_in_List ( s : Simplex; l : List ) return boolean is
246:
247: -- DESCRIPTION :
248: -- Returns true if the simplex s has vertices in the list l.
249:
250: pts : constant VecVec := Vertices(s);
251:
252: begin
253: for k in pts'range loop
254: if Is_In(l,pts(k).all)
255: then return true;
256: end if;
257: end loop;
258: return false;
259: end Has_Vertices_in_List;
260:
261: procedure Update_One
262: ( t : in out Triangulation; x : in Link_to_Vector ) is
263:
264: s : Simplex := Head_Of(t);
265: news,nei : Simplex;
266: nwt,leaves : Triangulation;
267: root : Hash_Table(2*x'last-1);
268: pos : Vector(0..x'last);
269: border_vertices : List;
270:
271: procedure Process_Tree_of_Updates is
272:
273: -- DESCRIPTION :
274: -- Constructs a tree of adjencencies which consists of
275: -- connected simplices on the edge of the triangulation.
276:
277: tmp,newleaves : Triangulation;
278: si,neisi : Simplex;
279:
280: begin
281: -- INITIALIZATION :
282: --Construct(s,root);
283: Init(root,x'first,x'last);
284: Update(root,s);
285: for k in x'range loop
286: declare
287: nei : Simplex := Neighbor(s,k);
288: begin
289: if (nei /= Null_Simplex) and then not Is_Vertex(nei,x.all)
290: then Construct(nei,leaves);
291: end if;
292: end;
293: end loop;
294: -- PERFORM THE UPDATES :
295: loop
296: -- INVARIANT CONDITION :
297: -- the simplices considered have vertices on the border close to x
298: newleaves := Null_Triangulation;
299: tmp := leaves;
300: while not Is_Null(tmp) loop
301: si := Head_Of(tmp);
302: -- UPDATE root TO PREVENT TURNING BACK :
303: Update(root,si);
304: -- COMPUTE NEW SIMPLICES AND LEAVES :
305: if not Is_Inner(x'last,si)
306: then pos := Position(si,x.all);
307: for k in x'range loop
308: -- LOOK IN THE DIRECTION TOWARDS x :
309: if pos(k-1)*pos(pos'last) > 0
310: then neisi := Neighbor(si,k);
311: if neisi = Null_Simplex
312: then Update(si,x,k); -- NEW SIMPLEX
313: neisi := Neighbor(si,k);
314: Construct(neisi,nwt);
315: Collect_Vertices(neisi,border_vertices);
316: end if;
317: end if;
318: end loop;
319: end if;
320: for l in x'range loop -- GO FURTHER
321: neisi := Neighbor(si,l);
322: if (neisi /= Null_Simplex)
323: and then not Is_Vertex(neisi,x.all)
324: and then Has_Vertices_in_List(neisi,border_vertices)
325: and then not Is_In(leaves,neisi)
326: and then not Is_In(newleaves,neisi)
327: and then not Is_In(root,neisi)
328: then Construct(neisi,newleaves);
329: end if;
330: end loop;
331: tmp := Tail_Of(tmp);
332: end loop;
333: exit when (newleaves = Null_Triangulation);
334: Lists_of_Simplices.Clear(Lists_of_Simplices.List(leaves));
335: leaves := newleaves;
336: end loop;
337: -- SHALLOW CLEAR :
338: -- Lists_of_Simplices.Clear(Lists_of_Simplices.List(root));
339: -- put_line("Distribution of root : "); Write_Distribution(root);
340: Clear(root);
341: Lists_of_Simplices.Clear(Lists_of_Simplices.List(leaves));
342: end Process_Tree_of_Updates;
343:
344: begin
345: nei := s; -- USED TO SEE WHETHER s WILL CHANGE
346: pos := Position(s,x.all);
347: Update_One(s,x,pos,news);
348: Construct(news,nwt);
349: Collect_Vertices(news,border_vertices);
350: if s /= nei
351: then pos := Position(s,x.all); -- BECAUSE s IS CHANGED !!!
352: end if;
353: for k in x'range loop -- COMPUTE OTHER NEIGHBORS
354: if pos(k-1)*pos(pos'last) > 0
355: then nei := Neighbor(s,k);
356: if nei = Null_Simplex
357: then Update(s,x,k);
358: nei := Neighbor(s,k);
359: Construct(nei,nwt);
360: Collect_Vertices(nei,border_vertices);
361: end if;
362: end if;
363: end loop;
364: Process_Tree_of_Updates;
365: Clear(border_vertices);
366: Connect_and_Update(nwt,t);
367: Lists_of_Simplices.Clear(Lists_of_Simplices.List(nwt));
368: end Update_One;
369:
370: procedure Connect ( t : in out Triangulation ) is
371:
372: tmp1 : Triangulation := t;
373: tmp2 : Triangulation;
374: s1,s2 : Simplex;
375:
376: begin
377: while not Is_Null(tmp1) loop
378: s1 := Head_Of(tmp1);
379: tmp2 := Tail_Of(tmp1);
380: while not Is_Null(tmp2) loop
381: s2 := Head_Of(tmp2);
382: Connect(s1,s2);
383: --Set_Head(tmp2,s2);
384: tmp2 := Tail_Of(tmp2);
385: end loop;
386: --Set_Head(tmp1,s1);
387: tmp1 := Tail_Of(tmp1);
388: end loop;
389: end Connect;
390:
391: -- THE OPTIMAL DISCRETE CONSERVATIVE LIFTING FUNCTION :
392:
393: -- procedure Write_Neighbors ( s : in Simplex ) is
394: -- begin
395: -- put("The normal of simplex s : "); put(Normal(s)); new_line;
396: -- put_line(" with vertices : "); put(s);
397: -- for k in Normal(s)'range loop
398: -- if Neighbor(s,k) /= Null_Simplex
399: -- then put("normal of a not null neighbors of s :");
400: -- put(Normal(Neighbor(s,k))); new_line;
401: -- end if;
402: -- end loop;
403: -- end Write_Neighbors;
404:
405: -- procedure Write ( t : in Triangulation ) is
406: --
407: -- tmp : Triangulation := t;
408: --
409: -- begin
410: -- while not Is_Null(tmp) loop
411: -- Write_Neighbors(Head_Of(tmp));
412: -- tmp := Tail_Of(tmp);
413: -- end loop;
414: -- end Write;
415:
416: procedure Flatten ( t : in out Triangulation ) is
417:
418: tmp : Triangulation := t;
419: s : Simplex;
420:
421: -- IMPLEMENTATION REQUIREMENT :
422: -- Cells that are already flattened are grouped at the end of the list.
423:
424: begin
425: -- put_line("THE TRIANGULATION BEFORE LIFTING : "); Write(t);
426: while not Is_Null(tmp) loop
427: s := Head_Of(tmp);
428: exit when Is_Flat(s);
429: -- put_line("NEIGHBORS BEFORE FLATTENING : "); Write_Neighbors(s);
430: Flatten(s);
431: -- put_line("NEIGHBORS AFTER FLATTENING : "); Write_Neighbors(s);
432: --Set_Head(tmp,s);
433: tmp := Tail_Of(tmp);
434: end loop;
435: -- put_line("THE TRIANGULATION AFTER LIFTING : "); Write(t);
436: end Flatten;
437:
438: -- SELECTORS :
439:
440: function Is_Vertex ( t : Triangulation; x : Vector ) return boolean is
441:
442: tmp : Triangulation := t;
443:
444: begin
445: while not Is_Null(tmp) loop
446: if Is_Vertex(Head_Of(tmp),x)
447: then return true;
448: end if;
449: tmp := Tail_Of(tmp);
450: end loop;
451: return false;
452: end Is_Vertex;
453:
454: function Vertices ( t : Triangulation ) return List is
455:
456: -- DESCRIPTION :
457: -- Returns a list with all vertices in the simplices of t.
458:
459: res,res_last : List;
460: tmp : Triangulation := t;
461:
462: begin
463: res_last := res;
464: while not Is_Null(tmp) loop
465: declare
466: s : Simplex := Head_Of(tmp);
467: v : constant VecVec := Vertices(s);
468: begin
469: for i in v'range loop
470: if not Is_In(res,v(i))
471: then Append(res,res_last,v(i));
472: end if;
473: end loop;
474: end;
475: tmp := Tail_Of(tmp);
476: end loop;
477: return res;
478: end Vertices;
479:
480: function Vertices ( t : Triangulation; x : vector ) return List is
481:
482: res,res_last : List;
483: tmp : Triangulation := t;
484:
485: begin
486: res_last := res;
487: while not Is_Null(tmp) loop
488: declare
489: s : Simplex := Head_Of(tmp);
490: begin
491: if Is_Vertex(s,x)
492: then
493: declare
494: v : constant VecVec := Vertices(s);
495: begin
496: for i in v'range loop
497: if not Is_In(res,v(i))
498: then Append(res,res_last,v(i));
499: end if;
500: end loop;
501: end;
502: end if;
503: tmp := Tail_Of(tmp);
504: end;
505: end loop;
506: return res;
507: end Vertices;
508:
509: function Vertices ( t : Triangulation ) return VecVec is
510:
511: vertri : List := Vertices(t);
512: res : VecVec(1..Length_Of(vertri));
513: tmp : List := vertri;
514:
515: begin
516: for i in res'range loop
517: res(i) := Head_Of(tmp);
518: tmp := Tail_Of(tmp);
519: end loop;
520: Shallow_Clear(vertri);
521: -- Lists_of_Link_to_Integer_Vectors.Clear
522: -- (Lists_of_Link_to_Integer_Vectors.List(vertri));
523: return res;
524: end Vertices;
525:
526: function Vertices ( t : Triangulation; x : vector ) return VecVec is
527:
528: vertri : List := Vertices(t,x);
529: res : VecVec(1..Length_Of(vertri));
530: tmp : List := vertri;
531:
532: begin
533: for i in res'range loop
534: res(i) := Head_Of(tmp);
535: tmp := Tail_Of(tmp);
536: end loop;
537: Shallow_Clear(vertri);
538: -- Lists_of_Link_to_Integer_Vectors.Clear
539: -- (Lists_of_Link_to_Integer_Vectors.List(vertri));
540: return res;
541: end Vertices;
542:
543: function Is_In1 ( t : Triangulation; x : Vector ) return boolean is
544:
545: tmp : Triangulation := t;
546:
547: begin
548: while not Is_Null(tmp) loop
549: if Is_In(Head_Of(tmp),x)
550: then return true;
551: end if;
552: tmp := Tail_Of(tmp);
553: end loop;
554: return false;
555: end Is_In1;
556:
557: function Is_In ( t : Triangulation; x : Vector ) return boolean is
558: begin
559: return Is_In_All(Head_Of(t),x);
560: end Is_In;
561:
562: function Is_In ( t : Triangulation; x : Vector ) return Simplex is
563: begin
564: return Is_In_All(Head_Of(t),x);
565: end Is_In;
566:
567: function Is_In ( t : Triangulation; s : Simplex ) return boolean is
568:
569: tmp : Triangulation := t;
570:
571: begin
572: -- put("Length of triangulation : "); put(Length_Of(t),1); new_line;
573: while not Is_Null(tmp) loop
574: if Equal(s,Head_Of(tmp))
575: then return true;
576: else tmp := Tail_Of(tmp);
577: end if;
578: end loop;
579: return false;
580: end Is_In;
581:
582: function Volume ( t : Triangulation ) return natural is
583:
584: tmp : Triangulation := t;
585: vol : natural := 0;
586:
587: begin
588: while not Is_Null(tmp) loop
589: vol := vol + Volume(Head_Of(tmp));
590: tmp := Tail_Of(tmp);
591: end loop;
592: return vol;
593: end Volume;
594:
595: -- DESTRUCTOR :
596:
597: procedure Clear ( t : in out Triangulation ) is
598:
599: tmp : Triangulation := t;
600:
601: begin
602: while not Is_Null(tmp) loop
603: declare
604: s : Simplex := Head_Of(tmp);
605: begin
606: Clear(s);
607: end;
608: tmp := Tail_Of(tmp);
609: end loop;
610: Lists_of_Simplices.Clear(Lists_of_Simplices.List(t));
611: end Clear;
612:
613: end Triangulations;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>