[BACK]Return to floating_linear_inequalities.adb CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / PHC / Ada / Math_Lib / Supports

Annotation of OpenXM_contrib/PHC/Ada/Math_Lib/Supports/floating_linear_inequalities.adb, Revision 1.1.1.1

1.1       maekawa     1: with Standard_Mathematical_Functions;    use Standard_Mathematical_Functions;
                      2: with Givens_Rotations;                   use Givens_Rotations;
                      3:
                      4: package body Floating_Linear_Inequalities is
                      5:
                      6: -- USAGE OF LP :
                      7:
                      8:   procedure Is_In_Cone ( tab : in out Matrix; lastcol : in integer;
                      9:                          rhs : in out Standard_Floating_Vectors.Vector;
                     10:                          tol : in double_float;
                     11:                          solution : out Standard_Floating_Vectors.Vector;
                     12:                          columns : out Standard_Integer_Vectors.Vector;
                     13:                          feasible : out boolean ) is
                     14:
                     15:   -- ALGORITHM:
                     16:   --   The following linear program will be solved:
                     17:   --
                     18:   --    min u_1 + .. + u_n
                     19:   --
                     20:   --        l_1*p_1i + l_2*p_2i + .. + l_m*p_mi + u_i*q_i = q_i   i=1,2,..,n
                     21:   --
                     22:   --  to determine whether q belongs to the cone spanned by the
                     23:   --  vectors p_1,p_2,..,p_m.
                     24:   --  If all u_i are zero and all constraints are satisfied,
                     25:   --  then q belongs to the cone spanned by the vectors.
                     26:
                     27:   -- CONSTANTS :
                     28:
                     29:     n  : constant natural := rhs'last;
                     30:     m  : constant natural := 2*n;             -- number of constraints
                     31:     nb : constant natural := lastcol+n;       -- number of unknowns
                     32:
                     33:   -- VARIABLES :
                     34:
                     35:     mat : matrix(0..m,0..nb);
                     36:     sol : Standard_Floating_Vectors.Vector(1..nb) := (1..nb => 0.0);
                     37:     bas : Standard_Integer_Vectors.Vector(1..m) := (1..m => 0);
                     38:     slk : Standard_Integer_Vectors.Vector(1..nb) := (1..nb => 0);
                     39:
                     40:     cnt : natural;
                     41:     s : double_float;
                     42:
                     43:   begin
                     44:
                     45:    -- INITIALIZATION OF THE TARGET :
                     46:
                     47:     for i in 0..(nb-n) loop
                     48:       mat(0,i) := 0.0;              -- sum of the lambda's
                     49:     end loop;
                     50:     for i in (nb-n+1)..nb loop
                     51:       mat(0,i) := -1.0;             -- sum of the mu's
                     52:     end loop;
                     53:
                     54:    -- INITIALIZATION OF THE CONSTRAINTS :
                     55:
                     56:     for i in 1..n loop
                     57:       for j in (nb-n+1)..nb loop
                     58:         if i /= j-nb+n
                     59:          then mat(i,j)   := 0.0;
                     60:               mat(i+n,j) := 0.0;
                     61:         end if;
                     62:       end loop;
                     63:     end loop;
                     64:
                     65:     for j in tab'first(2)..lastcol loop
                     66:       for i in tab'range(1) loop
                     67:         mat(i,j)   := -tab(i,j);
                     68:         mat(i+n,j) :=  tab(i,j);
                     69:       end loop;
                     70:     end loop;
                     71:
                     72:     for i in rhs'range loop
                     73:       mat(i,0)   := -rhs(i);
                     74:       mat(i+n,0) :=  rhs(i);
                     75:       mat(i,i+nb-n)   := -rhs(i);
                     76:       mat(i+n,i+nb-n) :=  rhs(i);
                     77:     end loop;
                     78:
                     79:   -- SOLVE THE LINEAR PROGRAM :
                     80:
                     81:    -- New_Tableau.Init_Basis(nb,bas,slk);
                     82:    -- Dual_Simplex(mat,sol,bas,slk,tol,false);
                     83:
                     84:   -- RETURN AND CHECK THE SOLUTION :
                     85:
                     86:     cnt := 0;
                     87:     for i in tab'first(2)..lastcol loop
                     88:       if abs(sol(i)) > tol
                     89:        then cnt := cnt + 1;
                     90:             solution(cnt) := sol(i);
                     91:             columns(cnt) := i;
                     92:       end if;
                     93:     end loop;
                     94:
                     95:     s := 0.0;
                     96:     for i in (nb-n+1)..nb loop
                     97:       s := s + sol(i);
                     98:     end loop;
                     99:     if abs(s) > tol
                    100:      then feasible := false; return;
                    101:     end if;
                    102:     feasible := true;
                    103:
                    104:   end Is_In_Cone;
                    105:
                    106: -- AUXILIARIES :
                    107:
                    108:   function Index_of_Maximum ( v : Standard_Floating_Vectors.Vector;
                    109:                               lst : integer ) return integer is
                    110:
                    111:   -- DESCRIPTION :
                    112:   --   Returns the index in the vector v(v'first..lst) for which the maximum
                    113:   --   is obtained.
                    114:
                    115:     res : integer := v'first;
                    116:     max : double_float := v(res);
                    117:
                    118:   begin
                    119:     for i in v'first+1..lst loop
                    120:       if v(i) > max
                    121:        then max := v(i); res := i;
                    122:       end if;
                    123:     end loop;
                    124:     return res;
                    125:   end Index_of_Maximum;
                    126:
                    127:   function Norm ( v : Standard_Floating_Vectors.Vector ) return double_float is
                    128:
                    129:   -- DESCRIPTION :
                    130:   --   Returns the 2-norm of the vector.
                    131:
                    132:     res : double_float := 0.0;
                    133:
                    134:   begin
                    135:     for j in v'range loop
                    136:       res := res + v(j)*v(j);
                    137:     end loop;
                    138:     if res + 1.0 = 1.0
                    139:      then return 0.0;
                    140:      else return SQRT(res);
                    141:     end if;
                    142:   end Norm;
                    143:
                    144:   function Norm ( v : Standard_Floating_Vectors.vector;
                    145:                   frst : integer ) return double_float is
                    146:
                    147:   -- DESCRIPTION :
                    148:   --   Returns the 2-norm of the vector v(frst..v'last).
                    149:
                    150:     res : double_float := 0.0;
                    151:
                    152:   begin
                    153:     for j in frst..v'last loop
                    154:       res := res + v(j)*v(j);
                    155:     end loop;
                    156:     if res + 1.0 = 1.0
                    157:      then return 0.0;
                    158:      else return SQRT(res);
                    159:     end if;
                    160:   end Norm;
                    161:
                    162:   procedure Scale ( v : in out Standard_Floating_Vectors.vector ) is
                    163:
                    164:   -- DESCRIPTION :
                    165:   --   Returns the normed vector, i.e. v/Norm(v).
                    166:
                    167:     nrm : double_float := Norm(v);
                    168:
                    169:   begin
                    170:     if nrm + 1.0 /= 1.0
                    171:      then for i in v'range loop
                    172:             v(i) := v(i)/nrm;
                    173:           end loop;
                    174:     end if;
                    175:   end Scale;
                    176:
                    177:   function Norm ( mat : matrix; i : integer ) return double_float is
                    178:
                    179:   -- DESCRIPTION :
                    180:   --   Returns the 2-norm of the ith column in the matrix.
                    181:
                    182:     res : double_float := 0.0;
                    183:
                    184:   begin
                    185:     for j in mat'range(1) loop
                    186:       res := res + mat(j,i)*mat(j,i);
                    187:     end loop;
                    188:     if res + 1.0 = 1.0
                    189:      then return 0.0;
                    190:      else return SQRT(res);
                    191:     end if;
                    192:   end Norm;
                    193:
                    194:   procedure Scale ( mat : in out matrix; lastcolumn : in integer ) is
                    195:
                    196:   -- DESCRIPTION :
                    197:   --   Scales the columns in the matrix, by dividing by their norm.
                    198:
                    199:     nrm : double_float;
                    200:
                    201:   begin
                    202:     for i in mat'first(2)..lastcolumn loop
                    203:       nrm := Norm(mat,i);
                    204:       if nrm + 1.0 /= 1.0
                    205:        then for j in mat'range(1) loop
                    206:               mat(j,i) := mat(j,i)/nrm;
                    207:             end loop;
                    208:       end if;
                    209:     end loop;
                    210:   end Scale;
                    211:
                    212:   function Inner_Product ( mat : Matrix; i : integer;
                    213:                            v : Standard_Floating_Vectors.Vector )
                    214:                          return double_float is
                    215:   -- DESCRIPTION :
                    216:   --   Computes the inner product of the given vector v and the vector
                    217:   --   in the ith column of the matrix.
                    218:
                    219:     res : double_float := 0.0;
                    220:
                    221:   begin
                    222:     for k in mat'range(1) loop
                    223:       res := res + mat(k,i)*v(k);
                    224:     end loop;
                    225:     return res;
                    226:   end Inner_Product;
                    227:
                    228:   function Maximal_Product ( mat : matrix; i : integer;
                    229:                              v : Standard_Floating_Vectors.Vector;
                    230:                              frst : integer ) return integer is
                    231:   -- DESCRIPTION :
                    232:   --   Returns the index in v(frst..v'last) for which mat(index,i)*v(index)
                    233:   --   becomes maximal.
                    234:
                    235:     res : integer := frst;
                    236:     max : double_float := mat(res,i)*v(res);
                    237:     tmp : double_float;
                    238:
                    239:   begin
                    240:     for j in frst+1..v'last loop
                    241:       tmp := mat(j,i)*v(j);
                    242:       if tmp > max
                    243:        then max := tmp; res := j;
                    244:       end if;
                    245:     end loop;
                    246:     return res;
                    247:   end Maximal_Product;
                    248:
                    249:   function Inner_Product ( mat : Matrix; i,j : integer ) return double_float is
                    250:
                    251:   -- DESCRIPTION :
                    252:   --   Computes the inner product of the vectors in the columns i and j
                    253:   --   of the matrix.
                    254:
                    255:     res : double_float := 0.0;
                    256:
                    257:   begin
                    258:     for k in mat'range(1) loop
                    259:       res := res + mat(k,i)*mat(k,j);
                    260:     end loop;
                    261:     return res;
                    262:   end Inner_Product;
                    263:
                    264:   function Inner_Products ( mat : matrix; lastcol : integer;
                    265:                             v : Standard_Floating_Vectors.Vector )
                    266:                           return Standard_Floating_Vectors.Vector is
                    267:
                    268:   -- DESCRIPTION :
                    269:   --   Returns a vector with all inner products of the given vector
                    270:   --   and the column vectors of the matrix.
                    271:
                    272:     res : Standard_Floating_Vectors.Vector(mat'first(2)..lastcol);
                    273:
                    274:   begin
                    275:     for i in res'range loop
                    276:       res(i) := Inner_Product(mat,i,v);
                    277:     end loop;
                    278:     return res;
                    279:   end Inner_Products;
                    280:
                    281:   function Positive ( v : Standard_Floating_Vectors.Vector;
                    282:                       lst : integer; tol : double_float )
                    283:                     return boolean is
                    284:   -- DESCRIPTION :
                    285:   --   Returns true if all elements in v(v'first..lst) are >= 0.
                    286:
                    287:   begin
                    288:     for i in v'first..lst loop
                    289:       if abs(v(i)) > tol and then (v(i) < 0.0)
                    290:        then return false;
                    291:       end if;
                    292:     end loop;
                    293:     return true;
                    294:   end Positive;
                    295:
                    296:   function Positive
                    297:                ( mat : matrix; rhs : Standard_Floating_Vectors.Vector;
                    298:                  ind,col : integer;
                    299:                  solind : double_float; tol : double_float ) return boolean is
                    300:
                    301:   -- DESCRIPTION :
                    302:   --   The given matrix is upper triangular up to the column indicated
                    303:   --   by ind.  This function returns true when by replacing column ind
                    304:   --   by column col, a positive solution would be obtained.
                    305:   --   The number solind is sol(ind) in the solution vector.
                    306:
                    307:     sol : Standard_Floating_Vectors.Vector(1..ind) := (1..ind => 0.0);
                    308:
                    309:   begin
                    310:     sol(ind) := solind;
                    311:     for i in reverse mat'first(1)..(ind-1) loop
                    312:       for j in i+1..(ind-1) loop
                    313:         sol(i) := sol(i) + mat(i,j)*sol(j);
                    314:       end loop;
                    315:       sol(i) := sol(i) + mat(i,col)*sol(ind);
                    316:       sol(i) := (rhs(i) - sol(i))/mat(i,i);
                    317:       if (abs(sol(i)) > tol) and then (sol(i) < 0.0)
                    318:        then --put_line("The solution before returning false : ");
                    319:             --put(sol,3,3,3); new_line;
                    320:             return false;
                    321:       end if;
                    322:     end loop;
                    323:     --put_line("The solution before returning true : ");
                    324:     --put(sol,3,3,3); new_line;
                    325:     return true;
                    326:   end Positive;
                    327:
                    328:   function Positive_Diagonal
                    329:                ( mat : Matrix; rhs : Standard_Floating_Vectors.Vector;
                    330:                  ind,col : integer;
                    331:                  solind : double_float; tol : double_float ) return boolean is
                    332:
                    333:   -- DESCRIPTION :
                    334:   --   The given matrix is diagonal up to the column indicated
                    335:   --   by ind.  This function returns true when by replacing column ind
                    336:   --   by column col, a positive solution would be obtained.
                    337:   --   The number solind is sol(ind) in the solution vector.
                    338:
                    339:     sol : Standard_Floating_Vectors.Vector(1..ind) := (1..ind => 0.0);
                    340:
                    341:   begin
                    342:     sol(ind) := solind;
                    343:     for i in reverse mat'first(1)..(ind-1) loop
                    344:       sol(i) := (rhs(i) - mat(i,col)*sol(ind))/mat(i,i);
                    345:       if (abs(sol(i)) > tol) and then (sol(i) < 0.0)
                    346:        then --put_line("The solution before returning false : ");
                    347:             --put(sol,3,3,3); new_line;
                    348:             return false;
                    349:       end if;
                    350:     end loop;
                    351:     --put_line("The solution before returning true : ");
                    352:     --put(sol,3,3,3); new_line;
                    353:     return true;
                    354:   end Positive_Diagonal;
                    355:
                    356: -- PIVOTING PROCEDURES :
                    357:
                    358:   procedure Interchange ( v : in out Standard_Floating_Vectors.Vector;
                    359:                           i,j : in integer ) is
                    360:
                    361:   -- DESCRIPTION :
                    362:   --   The entries v(i) and v(j) are interchanged.
                    363:
                    364:     temp : double_float;
                    365:
                    366:   begin
                    367:     temp := v(i); v(i) := v(j); v(j) := temp;
                    368:   end Interchange;
                    369:
                    370:   procedure Interchange_Columns ( mat : in out matrix; i,j : in integer ) is
                    371:
                    372:   -- DESCRIPTION :
                    373:   --   The columns i and j of the given matrix are interchanged.
                    374:
                    375:     temp : double_float;
                    376:
                    377:   begin
                    378:     for k in mat'range(1) loop
                    379:       temp := mat(k,i); mat(k,i) := mat(k,j); mat(k,j) := temp;
                    380:     end loop;
                    381:   end Interchange_Columns;
                    382:
                    383:   procedure Interchange_Rows
                    384:                  ( mat : in out Matrix; lastcol : in integer;
                    385:                    v : in out Standard_Floating_Vectors.Vector;
                    386:                    i,j : in integer ) is
                    387:
                    388:   -- DESCRIPTION :
                    389:   --   The rows i and j of the given matrix and vector are interchanged.
                    390:
                    391:     temp : double_float;
                    392:
                    393:   begin
                    394:     for k in mat'first(2)..lastcol loop
                    395:       temp := mat(i,k); mat(i,k) := mat(j,k); mat(j,k) := temp;
                    396:     end loop;
                    397:     temp := v(i); v(i) := v(j); v(j) := temp;
                    398:   end Interchange_Rows;
                    399:
                    400:   procedure Rotate ( mat : in out Matrix; lastcol,i : in integer;
                    401:                      v : in out Standard_Floating_Vectors.Vector;
                    402:                      tol : in double_float ) is
                    403:
                    404:   -- DESCRIPTION :
                    405:   --   Performs Givens rotations on the matrix and vector such that
                    406:   --   mat(j,i) = 0, for all j > i.
                    407:
                    408:   -- NOTE :
                    409:   --   A diagonalization procedure constructs an orthonormal basis
                    410:   --   and does not preserve the angles between the vectors.
                    411:
                    412:     cosi,sine : double_float;
                    413:
                    414:   begin
                    415:     for j in i+1..mat'last(1) loop
                    416:       if abs(mat(j,i)) > tol
                    417:        then Givens_Factors(mat,i,j,cosi,sine);
                    418:             Givens_Rotation(mat,lastcol,i,j,cosi,sine);
                    419:             Givens_Rotation(v,i,j,cosi,sine);
                    420:       end if;
                    421:     end loop;
                    422:   end Rotate;
                    423:
                    424:   procedure Upper_Triangulate ( mat : in out Matrix; lastcol,i : in integer;
                    425:                                 v : in out Standard_Floating_Vectors.Vector;
                    426:                                 tol : in double_float ) is
                    427:
                    428:   -- DESCRIPTION :
                    429:   --   Makes the upper diagonal elements of the ith colume zero:
                    430:   --   mat(j,i) = 0, for all j /= i.
                    431:
                    432:     fac : double_float;
                    433:
                    434:   begin
                    435:     for j in mat'first(1)..(i-1) loop
                    436:       if (abs(mat(j,i)) > tol)
                    437:        then fac := mat(j,i)/mat(i,i);
                    438:             for k in i..lastcol loop
                    439:               mat(j,k) := mat(j,k) - fac*mat(i,k);
                    440:             end loop;
                    441:       end if;
                    442:     end loop;
                    443:   end Upper_Triangulate;
                    444:
                    445: -- INITIALIZE : COMPUTE CLOSEST VECTOR TO RHS
                    446:
                    447:   procedure Initialize
                    448:               ( tableau : in out Matrix; lastcol : in integer;
                    449:                 rhs,sol : in out Standard_Floating_Vectors.Vector;
                    450:                 tol : in double_float;
                    451:                 columns : in out Standard_Integer_Vectors.Vector;
                    452:                 cosines : out Standard_Floating_Vectors.Vector;
                    453:                 feasible : out boolean ) is
                    454:
                    455:   -- DESCRIPTION :
                    456:   --   Scales the tableau and right hand side by dividing by its norm.
                    457:   --   Then computes the vector of cosines.
                    458:   --   If no vector with positive cosine with the right hand side vector
                    459:   --   can be found, then the problem is not feasible, otherwise,
                    460:   --   the vector with largest positive cosine will be the first column.
                    461:   --   At last, this first column will be transformed to the unit vector,
                    462:   --   by means of Givens rotations.
                    463:   --   Then the first solution component equals the first component of
                    464:   --   the transformed right hand side vector.
                    465:
                    466:     ips : Standard_Floating_Vectors.Vector(tableau'first(2)..lastcol);
                    467:     index : integer;
                    468:
                    469:   begin
                    470:     Scale(tableau,lastcol); Scale(rhs);
                    471:    -- put_line("The tableau after scaling : "); put(tableau,3,3,3);
                    472:    -- put_line(" with scaled right hand side : "); put(rhs,3,3,3); new_line;
                    473:     ips := Inner_Products(tableau,lastcol,rhs);
                    474:     index := Index_of_Maximum(ips,lastcol);
                    475:     if (abs(ips(index)) < tol) or else (ips(index) < 0.0)
                    476:      then if index <= rhs'last
                    477:            then feasible := (abs(rhs(index)) < tol);
                    478:            else feasible := false;
                    479:           end if;
                    480:      else feasible := true;
                    481:           columns(columns'first) := index;
                    482:           columns(index) := columns'first;
                    483:           Interchange_Columns(tableau,tableau'first(2),index);
                    484:           Interchange(ips,tableau'first(2),index);
                    485:           index := Maximal_Product(tableau,tableau'first(2),rhs,rhs'first);
                    486:           if index /= tableau'first(2)
                    487:            then Interchange_Rows(tableau,lastcol,rhs,tableau'first(2),index);
                    488:           end if;
                    489:           Rotate(tableau,lastcol,tableau'first(2),rhs,tol);
                    490:          -- Upper_Triangulate(tableau,lastcol,tableau'first(2),rhs,tol);
                    491:           sol(sol'first) := rhs(rhs'first);
                    492:     end if;
                    493:     cosines := ips;
                    494:    -- put_line("At the end of Initialize : ");
                    495:    -- put(" cosines : "); put(ips,3,3,3); new_line;
                    496:    -- put_line("The tableau : "); put(tableau,3,3,3);
                    497:    -- put_line(" with right hand side : "); put(rhs,3,3,3); new_line;
                    498:    -- put(" and last column "); put(lastcol,1); new_line;
                    499:   end Initialize;
                    500:
                    501:   procedure Initialize
                    502:               ( tableau : in out Matrix; lastcol : in integer;
                    503:                 rhs,sol : in out Standard_Floating_Vectors.Vector;
                    504:                 tol : in double_float;
                    505:                 columns : in out Standard_Integer_Vectors.Vector;
                    506:                 feasible : out boolean ) is
                    507:
                    508:   -- DESCRIPTION :
                    509:   --   Scales the tableau and right hand side by dividing by its norm.
                    510:   --   Then computes the vector of cosines.
                    511:   --   If no vector with positive cosine with the right hand side vector
                    512:   --   can be found, then the problem is not feasible, otherwise,
                    513:   --   the vector with largest positive cosine will be the first column.
                    514:   --   At last, this first column will be transformed to the unit vector,
                    515:   --   by means of Givens rotations.
                    516:   --   Then the first solution component equals the first component of
                    517:   --   the transformed right hand side vector.
                    518:
                    519:     ips : Standard_Floating_Vectors.Vector(tableau'first(2)..lastcol);
                    520:     index : integer;
                    521:
                    522:   begin
                    523:     Scale(tableau,lastcol); Scale(rhs);
                    524:    -- put_line("The tableau after scaling : "); put(tableau,3,3,3);
                    525:    -- put_line(" with scaled right hand side : "); put(rhs,3,3,3); new_line;
                    526:     ips := Inner_Products(tableau,lastcol,rhs);
                    527:     index := Index_of_Maximum(ips,lastcol);
                    528:     if (abs(ips(index)) < tol) or else (ips(index) < 0.0)
                    529:      then if index <= rhs'last
                    530:            then feasible := (abs(rhs(index)) < tol);
                    531:            else feasible := false;
                    532:           end if;
                    533:      else feasible := true;
                    534:           columns(columns'first) := index;
                    535:           columns(index) := columns'first;
                    536:           Interchange_Columns(tableau,tableau'first(2),index);
                    537:           index := Maximal_Product(tableau,tableau'first(2),rhs,rhs'first);
                    538:           if index /= tableau'first(2)
                    539:            then Interchange_Rows(tableau,lastcol,rhs,tableau'first(2),index);
                    540:           end if;
                    541:           Rotate(tableau,lastcol,tableau'first(2),rhs,tol);
                    542:          -- Upper_Triangulate(tableau,lastcol,tableau'first(2),rhs,tol);
                    543:           sol(sol'first) := rhs(rhs'first);
                    544:     end if;
                    545:    -- put_line("At the end of Initialize : ");
                    546:    -- put_line("The tableau : "); put(tableau,3,3,3);
                    547:    -- put_line(" with right hand side : "); put(rhs,3,3,3); new_line;
                    548:    -- put(" and last column "); put(lastcol,1); new_line;
                    549:   end Initialize;
                    550:
                    551: -- PERFORM THE NEXT STEPS :
                    552:
                    553:   procedure Select_Column
                    554:                   ( mat : in Matrix; lastcol : in integer;
                    555:                     rhs,cosines : in Standard_Floating_Vectors.Vector;
                    556:                     index : in integer;
                    557:                     tol : in double_float; row,col : out integer ) is
                    558:   -- DESCRIPTION :
                    559:   --   Selects a column col with in matrix for which
                    560:   --    1) the cosine is maximal and
                    561:   --    2) row = Maximal_Product(mat,col,rhs,index), with mat(row,col) > 0.0
                    562:   --   If the resulting column is smaller than index, then no such column
                    563:   --   has been found.
                    564:
                    565:     cl : integer := index;
                    566:     maxcos,prod : double_float;
                    567:     rw : integer := Maximal_Product(mat,cl,rhs,index);
                    568:     mp : integer;
                    569:
                    570:   begin
                    571:    -- put_line("The tableau when Select_Column :"); put(mat,3,3,3);
                    572:    -- put_line(" with right hand side : "); put(rhs,3,3,3); new_line;
                    573:    -- put_line("and vector of cosines : "); put(cosines,3,3,3); new_line;
                    574:    -- put("The index : "); put(index,1); new_line;
                    575:     prod := mat(rw,cl)*rhs(rw);
                    576:     if prod > tol
                    577:       and then Positive(mat,rhs,index,cl,rhs(rw)/mat(rw,cl),tol)
                    578:               -- Positive_Diagonal(mat,rhs,index,cl,rhs(rw)/mat(rw,cl),tol)
                    579:      then maxcos := cosines(cl);
                    580:      else maxcos := -2.0;
                    581:     end if;
                    582:     for i in index+1..lastcol loop
                    583:       mp := Maximal_Product(mat,i,rhs,index);
                    584:      -- put("mp : "); put(mp,1); put(" when testing "); put(i,1);
                    585:      -- put_line("th column");
                    586:       prod := mat(mp,i)*rhs(mp);
                    587:       if prod > tol and then cosines(i) > maxcos
                    588:        then if Positive(mat,rhs,index,i,rhs(mp)/mat(mp,i),tol)
                    589:               -- Positive_Diagonal(mat,rhs,index,i,rhs(mp)/mat(mp,i),tol)
                    590:              then cl := i; rw := mp; maxcos := cosines(i);
                    591:             end if;
                    592:       end if;
                    593:     end loop;
                    594:    -- put("maximal cosine : "); put(maxcos,3,3,3); new_line;
                    595:     if maxcos >= -1.0
                    596:      then col := cl; row := rw;
                    597:          -- put("column : "); put(cl,1);
                    598:          -- put(" and row : "); put(rw,1); new_line;
                    599:      else col := index-1; row := index-1;
                    600:          -- put("column : "); put(index-1,1);
                    601:          -- put(" and row : "); put(index-1,1); new_line;
                    602:     end if;
                    603:   end Select_Column;
                    604:
                    605:   procedure Select_Column
                    606:                   ( mat : in Matrix; lastcol : in integer;
                    607:                     rhs : in Standard_Floating_Vectors.Vector;
                    608:                     index,column : in integer;
                    609:                     tol : in double_float; row,col : out integer ) is
                    610:   -- DESCRIPTION :
                    611:   --   Selects first column col with in matrix for which
                    612:   --    row = Maximal_Product(mat,col,rhs,index), with mat(row,col) > 0.0.
                    613:   --   If the resulting column is smaller than index, then no such column
                    614:   --   has been found.
                    615:
                    616:     cl : integer := index-1;
                    617:     prod : double_float;
                    618:     rw,mp : integer;
                    619:
                    620:   begin
                    621:    -- put_line("The tableau when Select_Column :"); put(mat,3,3,3);
                    622:    -- put_line(" with right hand side : "); put(rhs,3,3,3); new_line;
                    623:    -- put("The index : "); put(index,1); new_line;
                    624:     for i in column..lastcol loop
                    625:       mp := Maximal_Product(mat,i,rhs,index);
                    626:      -- put("mp : "); put(mp,1); put(" when testing "); put(i,1);
                    627:      -- put_line("th column");
                    628:       prod := mat(mp,i)*rhs(mp);
                    629:       if prod > tol
                    630:         and then Positive(mat,rhs,index,i,rhs(mp)/mat(mp,i),tol)
                    631:                 -- Positive_Diagonal(mat,rhs,index,i,rhs(mp)/mat(mp,i),tol)
                    632:        then cl := i; rw := mp;
                    633:       end if;
                    634:       exit when (cl >= index);
                    635:     end loop;
                    636:     if cl >= index
                    637:      then col := cl; row := rw;
                    638:          -- put("column : "); put(cl,1);
                    639:          -- put(" and row : "); put(rw,1); new_line;
                    640:      else col := index-1; row := index-1;
                    641:          -- put("column : "); put(index-1,1);
                    642:          -- put(" and row : "); put(index-1,1); new_line;
                    643:     end if;
                    644:   end Select_Column;
                    645:
                    646:   procedure Next ( tableau : in out Matrix; lastcol : in integer;
                    647:                    rhs,sol,cosines : in out Standard_Floating_Vectors.Vector;
                    648:                    pivots : in out Standard_Integer_Vectors.Vector;
                    649:                    tol : in double_float;
                    650:                    index : in integer; feasi : in out boolean ) is
                    651:
                    652:   -- DESCRIPTION :
                    653:   --   Selects one new column out of the tableau.
                    654:
                    655:   -- ON ENTRY :
                    656:   --   tableau     upper triangular up to the row and column index-1;
                    657:   --   lastcol     index of the last column of interest in the tableau;
                    658:   --   rhs         right hand side vector;
                    659:   --   sol         solution vector for the components 1..index;
                    660:   --   cosines     vector of cosines;
                    661:   --   pivots      vector of column interchangements;
                    662:   --   tol         tolerance to decide whether a number equals zero;
                    663:   --   index       indicator of the current step;
                    664:   --   feasi       must be true on entry.
                    665:
                    666:   -- ON RETURN :
                    667:   --   tableau     upper triangular up to the row and column index,
                    668:   --               under the condition that feasi remains true;
                    669:   --   rhs         transformed right hand side vector;
                    670:   --   sol         new solution, with additional meaningful component
                    671:   --               sol(index);
                    672:   --   cosines     eventually permuted vector of cosines:
                    673:   --               cosines(index) is the cosine of the (new) column,
                    674:   --               indicated by index, and the right hand side vector;
                    675:   --   pivots      updated vector of column interchangements;
                    676:   --   feasi       if true, then a new column which yields a positive
                    677:   --               contribution of the right hand side vector has been
                    678:   --               found, if this was not the case, then feasi is false;
                    679:
                    680:     col,row,tmp : integer;
                    681:
                    682:   begin
                    683:     Select_Column(tableau,lastcol,rhs,cosines,index,tol,row,col);
                    684:     if col < index
                    685:      then feasi := false;
                    686:      else feasi := true;
                    687:           if col /= index
                    688:            then tmp := pivots(col); pivots(col) := pivots(index);
                    689:                 pivots(index) := tmp;
                    690:                 Interchange_Columns(tableau,col,index);
                    691:                 Interchange(cosines,col,index);
                    692:           end if;
                    693:           if row /= index
                    694:            then Interchange_Rows(tableau,lastcol,rhs,row,index);
                    695:           end if;
                    696:           Rotate(tableau,lastcol,index,rhs,tol);
                    697:          -- Upper_Triangulate(tableau,lastcol,index,rhs,tol);
                    698:          -- Solve(tableau,rhs,tol,index,sol);  -- only needed at end
                    699:          -- feasi := Positive(sol,index,tol);  -- double check...
                    700:     end if;
                    701:   end Next;
                    702:
                    703:   procedure Next ( tableau : in out Matrix; lastcol : in integer;
                    704:                    rhs,sol : in out Standard_Floating_Vectors.Vector;
                    705:                    pivots : in out Standard_Integer_Vectors.Vector;
                    706:                    tol : in double_float;
                    707:                    index : in integer; rank : out integer;
                    708:                    feasi : in out boolean ) is
                    709:
                    710:   -- DESCRIPTION :
                    711:   --   Lexicographic enumeration of the candidates, stops when a feasible
                    712:   --   solution is encountered.
                    713:
                    714:   -- ON ENTRY :
                    715:   --   tableau     upper triangular up to the row and column index-1;
                    716:   --   lastcol     index of the last column of interest in the tableau;
                    717:   --   rhs         right hand side vector;
                    718:   --   sol         solution vector for the components 1..index;
                    719:   --   pivots      vector of column interchangements;
                    720:   --   tol         tolerance to decide whether a number equals zero;
                    721:   --   index       indicator of the current step;
                    722:   --   feasi       must be true on entry.
                    723:
                    724:   -- ON RETURN :
                    725:   --   tableau     upper triangular up to the row and column index,
                    726:   --               under the condition that feasi remains true;
                    727:   --   rhs         transformed right hand side vector;
                    728:   --   sol         new solution, with additional meaningful component
                    729:   --               sol(index);
                    730:   --   pivots      updated vector of column interchangements;
                    731:   --   rank        rank of the current tableau;
                    732:   --   feasi       if true, then a new column which yields a positive
                    733:   --               contribution of the right hand side vector has been
                    734:   --               found, if this was not the case, then feasi is false;
                    735:
                    736:     column,col,row,tmp : integer;
                    737:     stop : boolean := false;
                    738:
                    739:   begin
                    740:     column := index;
                    741:     loop
                    742:       Select_Column(tableau,lastcol,rhs,index,column,tol,row,col);
                    743:       if col < column
                    744:        then feasi := false; stop := true;
                    745:        else
                    746:          feasi := true;
                    747:          if col /= index
                    748:           then tmp := pivots(col); pivots(col) := pivots(index);
                    749:                pivots(index) := tmp;
                    750:                Interchange_Columns(tableau,col,index);
                    751:          end if;
                    752:          if row /= index
                    753:           then Interchange_Rows(tableau,lastcol,rhs,row,index);
                    754:          end if;
                    755:          Rotate(tableau,lastcol,index,rhs,tol);
                    756:         -- Upper_Triangulate(tableau,lastcol,index,rhs,tol);
                    757:          if (index = lastcol) or else (index = tableau'last(1))
                    758:                               or else (Norm(rhs,index+1) < tol)
                    759:           then stop := true; rank := index;
                    760:           else
                    761:             Next(tableau,lastcol,rhs,sol,pivots,tol,index+1,rank,feasi);
                    762:             if feasi
                    763:              then stop := true;
                    764:              else column := col+1;
                    765:             end if;
                    766:          end if;
                    767:       end if;
                    768:       exit when stop;
                    769:     end loop;
                    770:   end Next;
                    771:
                    772:   procedure Complementary_Slackness
                    773:                  ( tableau : in out matrix;
                    774:                    rhs : in out Standard_Floating_Vectors.Vector;
                    775:                    tol : in double_float;
                    776:                    solution : out Standard_Floating_Vectors.Vector;
                    777:                    columns : out Standard_Integer_Vectors.Vector;
                    778:                    feasible : out boolean ) is
                    779:   begin
                    780:     Complementary_Slackness
                    781:        (tableau,tableau'last(2),rhs,tol,solution,columns,feasible);
                    782:   end Complementary_Slackness;
                    783:
                    784:   procedure Complementary_Slackness1
                    785:                  ( tableau : in out Matrix; lastcol : in integer;
                    786:                    rhs : in out Standard_Floating_Vectors.Vector;
                    787:                    tol : in double_float;
                    788:                    solution : out Standard_Floating_Vectors.Vector;
                    789:                    columns : out Standard_Integer_Vectors.Vector;
                    790:                    feasible : out boolean ) is
                    791:
                    792:   -- NOTE :
                    793:   --   This version is a straigth forward search and finds not always
                    794:   --   the feasible solution.
                    795:
                    796:     feasi : boolean;
                    797:     pivots : Standard_Integer_Vectors.Vector(tableau'first(2)..lastcol);
                    798:     cosis : Standard_Floating_Vectors.Vector(tableau'first(2)..lastcol);
                    799:     sol : Standard_Floating_Vectors.Vector(rhs'range) := (rhs'range => 0.0);
                    800:     rank : integer;
                    801:
                    802:   begin
                    803:     for i in pivots'range loop  -- initialize vector of pivots
                    804:       pivots(i) := i;
                    805:     end loop;
                    806:     Initialize(tableau,lastcol,rhs,sol,tol,pivots,cosis,feasi);
                    807:     if feasi
                    808:      then
                    809:        if Norm(rhs,rhs'first+1) > tol  -- check whether residual > 0
                    810:         then
                    811:           if tableau'first(1)+1 > lastcol
                    812:            then feasi := false;
                    813:            else
                    814:              rank := 1;
                    815:              for i in tableau'first(1)+1..tableau'last(1) loop
                    816:                Next(tableau,lastcol,rhs,sol,cosis,pivots,tol,i,feasi);
                    817:                exit when not feasi;
                    818:                exit when (i = lastcol);
                    819:                rank := rank + 1;
                    820:                exit when (Norm(rhs,i+1) < tol);
                    821:              end loop;
                    822:              if feasi
                    823:               then Solve(tableau,rhs,tol,rank,sol);
                    824:              end if;
                    825:           end if;
                    826:        end if;
                    827:        if feasi and then (tableau'last(1) > lastcol)
                    828:         then feasi := (Norm(rhs,lastcol+1) < tol);
                    829:        end if;
                    830:        if feasi and then (Norm(sol) < tol)
                    831:         then feasi := (Norm(rhs) < tol);
                    832:        end if;
                    833:        solution := sol;
                    834:        if tableau'last(1) <= lastcol
                    835:         then
                    836:           for i in tableau'range(1) loop
                    837:             columns(i) := pivots(i);
                    838:           end loop;
                    839:         else
                    840:           for i in tableau'first(2)..lastcol loop
                    841:             columns(i) := pivots(i);
                    842:           end loop;
                    843:        end if;
                    844:     end if;
                    845:     feasible := feasi;
                    846:   end Complementary_Slackness1;
                    847:
                    848:   procedure Complementary_Slackness
                    849:                  ( tableau : in out Matrix; lastcol : in integer;
                    850:                    rhs : in out Standard_Floating_Vectors.Vector;
                    851:                    tol : in double_float;
                    852:                    solution : out Standard_Floating_Vectors.Vector;
                    853:                    columns : out Standard_Integer_Vectors.Vector;
                    854:                    feasible : out boolean ) is
                    855:
                    856:   -- NOTE :
                    857:   --   This version enumerates in a lexicographic order all candidates
                    858:   --   for entering the basis and stops when a feasible solution has been
                    859:   --   found.
                    860:
                    861:     feasi : boolean;
                    862:     pivots : Standard_Integer_Vectors.Vector(tableau'first(2)..lastcol);
                    863:     sol : Standard_Floating_Vectors.Vector(rhs'range) := (rhs'range => 0.0);
                    864:     ind,rank : integer;
                    865:
                    866:   begin
                    867:     for i in pivots'range loop  -- initialize vector of pivots
                    868:       pivots(i) := i;
                    869:     end loop;
                    870:     Initialize(tableau,lastcol,rhs,sol,tol,pivots,feasi);
                    871:     if feasi
                    872:      then
                    873:        if Norm(rhs,rhs'first+1) > tol  -- check whether residual > 0
                    874:         then
                    875:           if tableau'first(1)+1 > lastcol
                    876:            then feasi := false;
                    877:            else
                    878:              ind := tableau'first(1)+1;
                    879:              Next(tableau,lastcol,rhs,sol,pivots,tol,ind,rank,feasi);
                    880:              if feasi
                    881:               then Solve(tableau,rhs,tol,rank,sol);
                    882:              end if;
                    883:           end if;
                    884:        end if;
                    885:        if feasi and then (tableau'last(1) > lastcol)
                    886:         then feasi := (Norm(rhs,lastcol+1) < tol);
                    887:        end if;
                    888:        if feasi and then (Norm(sol) < tol)
                    889:         then feasi := (Norm(rhs) < tol);
                    890:        end if;
                    891:        solution := sol;
                    892:        if tableau'last(1) <= lastcol
                    893:         then
                    894:           for i in tableau'range(1) loop
                    895:             columns(i) := pivots(i);
                    896:           end loop;
                    897:         else
                    898:           for i in tableau'first(2)..lastcol loop
                    899:             columns(i) := pivots(i);
                    900:           end loop;
                    901:        end if;
                    902:     end if;
                    903:     feasible := feasi;
                    904:   end Complementary_Slackness;
                    905:
                    906:   procedure Complementary_Slackness2
                    907:                  ( tableau : in out Matrix; lastcol : in integer;
                    908:                    rhs : in out Standard_Floating_Vectors.Vector;
                    909:                    tol : in double_float;
                    910:                    solution : out Standard_Floating_Vectors.Vector;
                    911:                    columns : out Standard_Integer_Vectors.Vector;
                    912:                    feasible : out boolean ) is
                    913:
                    914:   -- NOTE :
                    915:   --   This version explicitly uses linear programming.
                    916:
                    917:   begin
                    918:     Is_In_Cone(tableau,lastcol,rhs,tol,solution,columns,feasible);
                    919:   end Complementary_Slackness2;
                    920:
                    921: end Floating_Linear_Inequalities;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>