[BACK]Return to inner_normal_cones.adb CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / Ada / Root_Counts / Stalift

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