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

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>