Annotation of OpenXM_contrib/PHC/Ada/Root_Counts/Stalift/inner_normal_cones.adb, Revision 1.1
1.1 ! maekawa 1: with Standard_Integer_Linear_Solvers; use Standard_Integer_Linear_Solvers;
! 2: with Transformations; use Transformations;
! 3: with Integer_Vectors_Utilities; use Integer_Vectors_Utilities;
! 4: with Lists_of_Vectors_Utilities; use Lists_of_Vectors_Utilities;
! 5: with Transforming_Integer_Vector_Lists; use Transforming_Integer_Vector_Lists;
! 6: with Vertices; use Vertices;
! 7:
! 8: package body Inner_Normal_Cones is
! 9:
! 10: -- NOTE ON THE IMPLEMENTATION :
! 11: -- There is a safety mode in which after each computation of the generators,
! 12: -- it is automatically tested whether the generators satisfy the
! 13: -- inequalities of the normal cone. If not, then the bug is reported and
! 14: -- a program_error is raised.
! 15:
! 16: -- AUXILIAIRIES :
! 17:
! 18: function Lower ( a1,b1,a2,b2 : integer ) return boolean is
! 19:
! 20: -- DESCRIPTION :
! 21: -- Returns true if a1/b1 < a2/b2, false otherwise.
! 22:
! 23: -- REQUIRED : b1 /= 0 and b2 /= 0.
! 24:
! 25: begin
! 26: if b1*b2 > 0
! 27: then return (a1*b2 - a2*b1 < 0);
! 28: else return (a1*b2 - a2*b1 > 0);
! 29: end if;
! 30: end Lower;
! 31:
! 32: function Higher ( a1,b1,a2,b2 : integer ) return boolean is
! 33:
! 34: -- DESCRIPTION :
! 35: -- Returns true if a1/b1 > a2/b2, false otherwise.
! 36:
! 37: -- REQUIRED : b1 /= 0 and b2 /= 0.
! 38:
! 39: begin
! 40: if b1*b2 > 0
! 41: then return (a1*b2 - a2*b1 > 0);
! 42: else return (a1*b2 - a2*b1 < 0);
! 43: end if;
! 44: end Higher;
! 45:
! 46: function Compute_Facets ( l : List; x : Vector ) return Faces is
! 47:
! 48: -- DESCRIPTION :
! 49: -- Returns all facets of conv(l) that all contain x.
! 50: -- Checks whether x belongs to the list or not.
! 51:
! 52: res : Faces;
! 53: n : constant natural := x'length;
! 54:
! 55: begin
! 56: if Is_In(l,x)
! 57: then res := Create(n-1,n,l,x);
! 58: else declare
! 59: wrk : List := l;
! 60: lx : Link_to_Vector;
! 61: begin
! 62: lx := new Vector'(x);
! 63: Construct(lx,wrk);
! 64: res := Create(n-1,n,wrk,x);
! 65: end;
! 66: end if;
! 67: return res;
! 68: end Compute_Facets;
! 69:
! 70: procedure Shifted_Points ( l : in List; x : in Vector;
! 71: res,res_last : in out List ) is
! 72:
! 73: -- DESCRIPTION :
! 74: -- Appends the list of shifted points w.r.t. x to the list res.
! 75:
! 76: tmp : List := l;
! 77:
! 78: begin
! 79: tmp := l;
! 80: while not Is_Null(tmp) loop
! 81: Append_Diff(res,res_last,Head_Of(tmp).all-x);
! 82: tmp := Tail_Of(tmp);
! 83: end loop;
! 84: end Shifted_Points;
! 85:
! 86: function In_Hull ( l : List; x : Vector ) return boolean is
! 87:
! 88: -- DESCRIPTION :
! 89: -- Returns true if the vector x belongs the convex hull spanned by
! 90: -- the points in l minus the point x itself.
! 91:
! 92: res : boolean;
! 93: lx : List;
! 94:
! 95: begin
! 96: Copy(l,lx);
! 97: Remove(lx,x);
! 98: res := Is_In_Hull(x,lx);
! 99: Clear(lx);
! 100: return res;
! 101: end In_Hull;
! 102:
! 103: -- AUXILIAIRIES TO CONSTRUCT THE NORMALS :
! 104:
! 105: procedure Normal ( m : in out Matrix; v : out Vector ) is
! 106:
! 107: -- DESCRIPTION :
! 108: -- Computes the normal to the vectors stored in the rows of the matrix m.
! 109:
! 110: -- REQUIRED : the matrix m is square!
! 111:
! 112: res : Vector(m'range(2));
! 113:
! 114: begin
! 115: Upper_Triangulate(m); Scale(m);
! 116: res := (res'range => 0);
! 117: Solve0(m,res);
! 118: v := res;
! 119: end Normal;
! 120:
! 121: procedure Orientate_Normal ( l : in List; f : in Face;
! 122: normal : in out Vector ) is
! 123:
! 124: -- DESCRIPTION :
! 125: -- Orientates the normal of the face such that it becomes an inner normal
! 126: -- w.r.t. the points in the list l.
! 127:
! 128: tmp : List := l;
! 129: ip : constant integer := f(f'first).all*normal;
! 130: pt : Vector(Head_Of(l)'range);
! 131: done : boolean := false;
! 132: ptip : integer;
! 133:
! 134: begin
! 135: while not Is_Null(tmp) loop
! 136: pt := Head_Of(tmp).all;
! 137: if not Is_In(f,pt)
! 138: then ptip := pt*normal;
! 139: if ptip /= ip
! 140: then if ptip < ip
! 141: then normal := -normal;
! 142: end if;
! 143: done := true;
! 144: end if;
! 145: end if;
! 146: exit when done;
! 147: tmp := Tail_Of(tmp);
! 148: end loop;
! 149: end Orientate_Normal;
! 150:
! 151: function Inner_Normal ( l : List; facet : Face ) return Vector is
! 152:
! 153: -- DESCRIPTION :
! 154: -- Returns the inner normal to the facet.
! 155:
! 156: res,fst : Vector(facet(facet'first)'range);
! 157: m : Matrix(facet'first+1..facet'last,facet(facet'first)'range);
! 158:
! 159: begin
! 160: fst := facet(facet'first).all;
! 161: for i in m'first(1)..m'last(1) loop
! 162: for j in m'range(2) loop
! 163: m(i,j) := facet(i)(j) - fst(j);
! 164: end loop;
! 165: end loop;
! 166: Normal(m,res);
! 167: Orientate_Normal(l,facet,res);
! 168: return res;
! 169: end Inner_Normal;
! 170:
! 171: procedure Inner_Normals ( l : in List; facets : in Faces;
! 172: iv,iv_last : in out List ) is
! 173:
! 174: -- DESCRIPTION :
! 175: -- Returns the list of all inner normals to the facets of conv(l).
! 176: -- If there is only one facet, then both `inner' and `outer' normal
! 177: -- will be returned, because there is nothing to orientate with.
! 178: -- This means that also the negation of the normal will be in the list iv.
! 179:
! 180: tmp : Faces := facets;
! 181:
! 182: begin
! 183: while not Is_Null(tmp) loop
! 184: declare
! 185: f : Face := Head_Of(tmp);
! 186: v : constant Vector := Inner_Normal(l,Head_Of(tmp));
! 187: begin
! 188: Append(iv,iv_last,v);
! 189: if Length_Of(facets) = 1
! 190: then Append(iv,iv_last,-v);
! 191: end if;
! 192: end;
! 193: tmp := Tail_Of(tmp);
! 194: end loop;
! 195: end Inner_Normals;
! 196:
! 197: function Number_of_Rows ( l : List ) return natural is
! 198:
! 199: -- DESCRIPTION :
! 200: -- Returns Maximum(dimension,Length_Of(l)).
! 201:
! 202: -- REQUIRED : not Is_Null(l).
! 203:
! 204: n : constant natural := Head_Of(l)'length;
! 205: m : constant natural := Length_Of(l);
! 206:
! 207: begin
! 208: if n > m
! 209: then return n;
! 210: else return m;
! 211: end if;
! 212: end Number_of_Rows;
! 213:
! 214: function Normal ( l : List ) return Vector is
! 215:
! 216: -- DESCRIPTION :
! 217: -- Return a normal to the vectors in the list.
! 218:
! 219: -- REQUIRED : Length_Of(l) <= n = Head_Of(l)'length
! 220: -- or the points in l all lie on the same facet.
! 221:
! 222: fst : Link_to_Vector := Head_Of(l);
! 223: m : Matrix(1..Number_of_Rows(l),fst'range);
! 224: cnt : natural := 0;
! 225: res : Vector(fst'range);
! 226: tmp : List := Tail_Of(l);
! 227:
! 228: begin
! 229: while not Is_Null(tmp) loop
! 230: res := Head_Of(tmp).all;
! 231: cnt := cnt+1;
! 232: for i in res'range loop
! 233: m(cnt,i) := res(i) - fst(i);
! 234: end loop;
! 235: tmp := Tail_Of(tmp);
! 236: end loop;
! 237: for i in cnt+1..m'last(1) loop
! 238: for j in m'range(2) loop
! 239: m(i,j) := 0;
! 240: end loop;
! 241: end loop;
! 242: Normal(m,res);
! 243: return res;
! 244: end Normal;
! 245:
! 246: procedure Normals ( l : in List; x : in Vector; iv,iv_last : in out List ) is
! 247:
! 248: -- DESCRIPTION :
! 249: -- Computes a list of all normals to the vectors in the list.
! 250:
! 251: -- REQUIRED : Length_Of(l) <= n = x'length.
! 252: -- or all points in l lie on the same facet.
! 253:
! 254: nor : constant Vector := Normal(l);
! 255: piv : natural := Pivot(nor);
! 256: pivnor : Vector(nor'range); -- normal with pivnor(piv) > 0
! 257:
! 258: begin
! 259: if piv <= nor'last
! 260: then if x'length > 2
! 261: then if nor(piv) < 0
! 262: then pivnor := -nor;
! 263: else pivnor := nor;
! 264: end if;
! 265: declare
! 266: t : Transfo := Build_Transfo(pivnor,piv);
! 267: tx : constant Vector := Reduce(t*x,piv);
! 268: tt : Transfo := Transpose(t);
! 269: tl : List := Transform_and_Reduce(t,piv,l);
! 270: begin
! 271: if Length_Of(tl) <= nor'length-1
! 272: then Normals(tl,tx,iv,iv_last);
! 273: else declare
! 274: facets : Faces := Compute_Facets(tl,tx);
! 275: begin
! 276: if Length_Of(facets) > 1
! 277: then Inner_Normals(tl,facets,iv,iv_last);
! 278: else Normals(tl,tx,iv,iv_last);
! 279: end if;
! 280: end;
! 281: end if;
! 282: Insert_and_Transform(iv,piv,0,tt);
! 283: iv_last := Pointer_to_Last(iv);
! 284: Clear(t); Deep_Clear(tl); Clear(tt);
! 285: end;
! 286: end if;
! 287: Append(iv,iv_last,nor); Append(iv,iv_last,-nor);
! 288: end if;
! 289: end Normals;
! 290:
! 291: -- CONSTRUCTORS FOR PRIMAL REPRESENTATION :
! 292:
! 293: function Generators ( l : List; facets : Faces; x : Vector ) return List is
! 294:
! 295: res,res_last : List;
! 296:
! 297: begin
! 298: if Length_Of(facets) > 1
! 299: then Inner_Normals(l,facets,res,res_last); -- compute inner normals
! 300: elsif In_Hull(l,x)
! 301: then return res; -- empty normal cone
! 302: else Normals(l,x,res,res_last); -- compute normals
! 303: if Length_Of(l) = 2
! 304: then Shifted_Points(l,x,res,res_last);
! 305: end if;
! 306: end if;
! 307: -- SAFETY MODE :
! 308: -- if not Contained_in_Cone(l,x,res)
! 309: -- then put_line("Bug raised for computing generators for list"); put(l);
! 310: -- put(" and the point : "); put(x); new_line;
! 311: -- raise PROGRAM_ERROR;
! 312: -- end if;
! 313: return res;
! 314: end Generators;
! 315:
! 316: function Generators ( l : List; x : Vector ) return List is
! 317:
! 318: res,res_last : List;
! 319: n : constant natural := x'length;
! 320: facets : Faces;
! 321:
! 322: begin
! 323: if In_Hull(l,x)
! 324: then return res; -- empty normal cone
! 325: else if Length_Of(l) > n
! 326: then facets := Compute_Facets(l,x);
! 327: end if;
! 328: if Length_Of(facets) > 1
! 329: then res := Generators(l,facets,x);
! 330: else Normals(l,x,res,res_last);
! 331: if Length_Of(l) = 2
! 332: then Shifted_Points(l,x,res,res_last);
! 333: end if;
! 334: end if;
! 335: -- SAFETY MODE :
! 336: -- if not Contained_in_Cone(l,x,res)
! 337: -- then put_line("Bug raised for computing generators for list");
! 338: -- put(l); put(" and the point : "); put(x); new_line;
! 339: -- raise PROGRAM_ERROR;
! 340: -- end if;
! 341: return res;
! 342: end if;
! 343: end Generators;
! 344:
! 345: -- CONSTRUCTOR FOR DUAL REPRESENTATION :
! 346:
! 347: function Inner_Normal_Cone ( l : List; x : Vector ) return Matrix is
! 348:
! 349: res : Matrix(x'range,1..Length_Of(l)-1);
! 350: -- CAUTION : Is_In(l,x) must hold !!
! 351: y : Vector(x'range);
! 352: cnt : natural := 0;
! 353: tmp : List := l;
! 354:
! 355: begin
! 356: while not Is_Null(tmp) loop
! 357: y := Head_Of(tmp).all;
! 358: if not Equal(x,y) -- avoid trivial inequality
! 359: then cnt := cnt+1;
! 360: for i in x'range loop
! 361: res(i,cnt) := y(i) - x(i);
! 362: end loop;
! 363: end if;
! 364: tmp := Tail_Of(tmp);
! 365: end loop;
! 366: return res;
! 367: end Inner_Normal_Cone;
! 368:
! 369: function Included_Normal_Cone ( gx : List; x : Vector ) return Matrix is
! 370:
! 371: res : Matrix(x'first-1..x'last,1..Length_Of(gx));
! 372: tmp : List := gx;
! 373: v : Vector(x'range);
! 374:
! 375: begin
! 376: for j in res'range(2) loop
! 377: v := Head_Of(tmp).all;
! 378: res(res'first(1),j) := x*v;
! 379: for i in res'first(1)+1..res'last(1) loop
! 380: res(i,j) := v(i);
! 381: end loop;
! 382: tmp := Tail_Of(tmp);
! 383: end loop;
! 384: return res;
! 385: end Included_Normal_Cone;
! 386:
! 387: -- PRIMITIVE SELECTORS :
! 388:
! 389: function Evaluate ( m : Matrix; i : integer; v : Vector ) return integer is
! 390:
! 391: sum : integer := 0;
! 392:
! 393: begin
! 394: for j in v'range loop
! 395: sum := sum + m(j,i)*v(j);
! 396: end loop;
! 397: return sum;
! 398: end Evaluate;
! 399:
! 400: function Satisfies ( m : Matrix; i : integer; v : Vector ) return boolean is
! 401: begin
! 402: if m'first(1) = v'first-1
! 403: then return (Evaluate(m,i,v) >= m(0,i));
! 404: else return (Evaluate(m,i,v) >= 0);
! 405: end if;
! 406: end Satisfies;
! 407:
! 408: function Strictly_Satisfies ( m : Matrix; i : integer; v : Vector )
! 409: return boolean is
! 410: begin
! 411: if m'first(1) = v'first-1
! 412: then return (Evaluate(m,i,v) > m(0,i));
! 413: else return (Evaluate(m,i,v) > 0);
! 414: end if;
! 415: end Strictly_Satisfies;
! 416:
! 417: function Satisfies ( m : Matrix; v : Vector ) return boolean is
! 418: begin
! 419: for i in m'range(2) loop
! 420: if not Satisfies(m,i,v)
! 421: then return false;
! 422: end if;
! 423: end loop;
! 424: return true;
! 425: end Satisfies;
! 426:
! 427: function Strictly_Satisfies ( m : Matrix; v : Vector ) return boolean is
! 428: begin
! 429: for i in m'range(2) loop
! 430: if not Strictly_Satisfies(m,i,v)
! 431: then return false;
! 432: end if;
! 433: end loop;
! 434: return true;
! 435: end Strictly_Satisfies;
! 436:
! 437: function Satisfies ( m : Matrix; v : List ) return boolean is
! 438:
! 439: tmp : List := v;
! 440:
! 441: begin
! 442: while not Is_Null(tmp) loop
! 443: if not Satisfies(m,Head_Of(tmp).all)
! 444: then return false;
! 445: else tmp := Tail_Of(tmp);
! 446: end if;
! 447: end loop;
! 448: return true;
! 449: end Satisfies;
! 450:
! 451: function Strictly_Satisfies ( m : Matrix; v : List ) return boolean is
! 452:
! 453: tmp : List := v;
! 454:
! 455: begin
! 456: while not Is_Null(tmp) loop
! 457: if not Strictly_Satisfies(m,Head_Of(tmp).all)
! 458: then return false;
! 459: else tmp := Tail_Of(tmp);
! 460: end if;
! 461: end loop;
! 462: return true;
! 463: end Strictly_Satisfies;
! 464:
! 465: -- SECONDARY SELECTORS :
! 466:
! 467: function Satisfy ( m : Matrix; l : List ) return List is
! 468:
! 469: res,res_last,tmp : List;
! 470:
! 471: begin
! 472: tmp := l;
! 473: while not Is_Null(tmp) loop
! 474: if Satisfies(m,Head_Of(tmp).all)
! 475: then Append(res,res_last,Head_Of(tmp).all);
! 476: end if;
! 477: tmp := Tail_Of(tmp);
! 478: end loop;
! 479: return res;
! 480: end Satisfy;
! 481:
! 482: function Strictly_Satisfy ( m : Matrix; l : List ) return List is
! 483:
! 484: res,res_last,tmp : List;
! 485:
! 486: begin
! 487: tmp := l;
! 488: while not Is_Null(tmp) loop
! 489: if Strictly_Satisfies(m,Head_Of(tmp).all)
! 490: then Append(res,res_last,Head_Of(tmp).all);
! 491: end if;
! 492: tmp := Tail_Of(tmp);
! 493: end loop;
! 494: return res;
! 495: end Strictly_Satisfy;
! 496:
! 497: function Contained_in_Cone ( l : List; x : Vector; v : List )
! 498: return boolean is
! 499:
! 500: ineq : Matrix(x'range,1..Length_Of(l)-1) := Inner_Normal_Cone(l,x);
! 501:
! 502: begin
! 503: return Satisfies(ineq,v);
! 504: end Contained_in_Cone;
! 505:
! 506: function Strictly_Contained_in_Cone ( l : List; x : Vector; v : List )
! 507: return boolean is
! 508:
! 509: ineq : Matrix(x'range,1..Length_Of(l)-1) := Inner_Normal_Cone(l,x);
! 510:
! 511: begin
! 512: return Strictly_Satisfies(ineq,v);
! 513: end Strictly_Contained_in_Cone;
! 514:
! 515: function Contained_in_Cone ( l,v : List ) return boolean is
! 516:
! 517: tmp : List := l;
! 518:
! 519: begin
! 520: while not Is_Null(tmp) loop
! 521: if Contained_in_Cone(l,Head_Of(tmp).all,v)
! 522: then -- put("true for vector : "); put(Head_Of(tmp).all); new_line;
! 523: return true;
! 524: else tmp := Tail_Of(tmp);
! 525: end if;
! 526: end loop;
! 527: return false;
! 528: end Contained_in_Cone;
! 529:
! 530: function Strictly_Contained_in_Cone ( l,v : List ) return boolean is
! 531:
! 532: tmp : List := l;
! 533:
! 534: begin
! 535: while not Is_Null(tmp) loop
! 536: if Strictly_Contained_in_Cone(l,Head_Of(tmp).all,v)
! 537: then return true;
! 538: else tmp := Tail_Of(tmp);
! 539: end if;
! 540: end loop;
! 541: return false;
! 542: end Strictly_Contained_in_Cone;
! 543:
! 544: -- CONCERNING THE UNION OF CONES :
! 545:
! 546: function In_Union ( v1,v2 : Vector; k1,k2 : Matrix ) return boolean is
! 547:
! 548: -- ALGORITHM : consider x(t) = (1-t)*v1 + t*v2, for t in [0,1]
! 549: -- and compute t1: smallest t such that Satisfies(k1,x(t))
! 550: -- and t2: largest t such that Satisfies(k2,x(t)).
! 551: -- Then t1 >= t2 makes the test returning true, false otherwise.
! 552:
! 553: diff : constant Vector := v1-v2;
! 554: t1a,t1b,t2a,t2b,a,b : integer; -- t1 = t1a/t1b and t2 = t2a/t2b
! 555:
! 556: begin
! 557: t1a := 1; t1b := 1; -- initially t1 = 1 = 1/1
! 558: for i in k1'range(2) loop
! 559: b := Evaluate(k1,i,diff);
! 560: if b /= 0
! 561: then a := Evaluate(k1,i,v1);
! 562: if Lower(a,b,t1a,t1b)
! 563: then t1a := a; t1b := b;
! 564: end if;
! 565: end if;
! 566: end loop;
! 567: t2a := 0; t2b := 1; -- initially t2 = 0 = 0/1
! 568: for i in k2'range(2) loop
! 569: b := Evaluate(k2,i,diff);
! 570: if b /= 0
! 571: then a := Evaluate(k2,i,v1);
! 572: if Higher(a,b,t2a,t2b)
! 573: then t2a := a; t2b := b;
! 574: end if;
! 575: end if;
! 576: end loop;
! 577: -- put("In_Union for "); put(v1); put(" and "); put(v2);
! 578: -- put(" : t1 = "); put(t1a,1); put("/"); put(t1b,1);
! 579: -- put(" : t2 = "); put(t2a,1); put("/"); put(t2b,1); new_line;
! 580: -- put_line("k1 : "); put(k1); put_line("k2 : "); put(k2);
! 581: return not Lower(t1a,t1b,t2a,t2b);
! 582: end In_Union;
! 583:
! 584: function In_Union ( v1,v2 : List; k1,k2 : Matrix ) return boolean is
! 585:
! 586: tmpv1,tmpv2 : List;
! 587:
! 588: begin
! 589: tmpv1 := v1;
! 590: while not Is_Null(tmpv1) loop
! 591: tmpv2 := v2;
! 592: while not Is_Null(tmpv2) loop
! 593: if not In_Union(Head_Of(tmpv1).all,Head_Of(tmpv2).all,k1,k2)
! 594: then return false;
! 595: else tmpv2 := Tail_Of(tmpv2);
! 596: end if;
! 597: end loop;
! 598: tmpv1 := Tail_Of(tmpv1);
! 599: end loop;
! 600: return true;
! 601: end In_Union;
! 602:
! 603: end Inner_Normal_Cones;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>