• More of my philosophy about the Simplex algorithm and method and more o

    From Amine Moulay Ramdane@21:1/5 to All on Thu Jun 16 17:11:50 2022
    Hello,



    More of my philosophy about the Simplex algorithm and method
    and more of my thoughts..

    I am a white arab, and i think i am smart since i have also
    invented many scalable algorithms and algorithms..


    I think i am highly smart, and i say that the Linear Programming Problem is by far the most widely used optimization model. Its impact on economic and government modeling is immense. The Simplex Method for solving the Linear Programming (LP) Problem, due
    to George Dantzig, has been an extremely efficient computational tool for almost four decades. In general, the simplex algorithm is extremely powerful, which usually takes 2m to 3m iterations at the most (here, m denotes the range of equality constraints)
    , and it converges in anticipated polynomial time for specific distributions of random input, and it is why i have just come with the Simplex algorithm and method below for Freepascal and Delphi compilers so that to solve Linear Programming (LP) Problem
    and i have enhanced it from a past release of a simplex program so that to work with both Delphi and Freepascal and so that to use Dynamic arrays so that to "scale", and here is my Freepascal and Delphi unit with a test program in Delphi and Freepascal
    that works perfectly:


    First, here is the source code of the unit for Freepascal and Delphi
    that i have enhanced (and you can download the freepascal 64 bit compiler from here: https://www.freepascal.org/ ):

    --------------------------------------------------------------------

    {***************************************************************
    * LINEAR PROGRAMMING: THE SIMPLEX METHOD *
    * ------------------------------------------------------------ *
    * SAMPLE RUN: *
    * Maximize z = x1 + x2 + 3x3 -0.5x4 with conditions: *
    * x1 + 2x3 <= 740 *
    * 2x2 - 7x4 <= 0 *
    * x2 - x3 + 2x4 >= 0.5 *
    * x1 + x2 + x3 +x4 = 9 *
    * and all x's >=0. *
    * *
    * Number of variables in E.F.: 4 *
    * Number of <= inequalities..: 2 *
    * Number of >= inequalities..: 1 *
    * Number of = equalities.....: 1 *
    * Input Economic Function: *
    * Coefficient # 1: 1 *
    * Coefficient # 2: 1 *
    * Coefficient # 3: 3 *
    * Coefficient # 4: -0.5 *
    * Constant term..: 0 *
    * Input constraint # 1: *
    * Coefficient # 1: 1 *
    * Coefficient # 2: 0 *
    * Coefficient # 3: 2 *
    * Coefficient # 4: 0 *
    * Constant term..: 740 *
    * Input constraint # 2: *
    * Coefficient # 1: 0 *
    * Coefficient # 2: 2 *
    * Coefficient # 3: 0 *
    * Coefficient # 4: -7 *
    * Constant term..: 0 *
    * Input constraint # 3: *
    * Coefficient # 1: 0 *
    * Coefficient # 2: 1 *
    * Coefficient # 3: -1 *
    * Coefficient # 4: 2 *
    * Constant term..: 0.5 *
    * Input constraint # 4: *
    * Coefficient # 1: 1 *
    * Coefficient # 2: 1 *
    * Coefficient # 3: 1 *
    * Coefficient # 4: 1 *
    * Constant term..: 9 *
    * *
    * Input Table: *
    * 0.00 1.00 1.00 3.00 -0.50 *
    * 740.00 -1.00 0.00 -2.00 0.00 *
    * 0.00 0.00 -2.00 0.00 7.00 *
    * 0.50 0.00 -1.00 1.00 -2.00 *
    * 9.00 -1.00 -1.00 -1.00 -1.00 *
    * *
    * Maximum of E.F. = 17.02500 *
    * X1 = 0.000000 *
    * X2 = 3.325000 *
    * X3 = 4.725000 *
    * X4 = 0.950000 *
    * *
    * ------------------------------------------------------------ *
    * Reference: "Numerical Recipes By W.H. Press, B. P. Flannery, *
    * S.A. Teukolsky and W.T. Vetterling, Cambridge *
    * University Press, 1986" [BIBLI 08]. *
    * *
    * Past release 1.0 By J-P Moreau, Paris *
    * New release by Amine Moulay Ramdane *
    * *
    * Note: This unit was enhanced by Amine Moulay Ramdane *
    * so that to work with both Delphi and Freepascal *
    * and so that to use Dynamic arrays so that to scale. * ***************************************************************}

    unit TSimplex;

    //Uses Crt;


    interface





    Type
    MAT = array of array of double;
    IVEC = array of integer;

    Var
    A: MAT;
    IPOSV, IZROV: IVEC;
    ICASE,N,M,M1,M2,M3 {i,j,}: Integer;
    R: REAL;

    Procedure simplx(var a:MAT; m, n, m1, m2, m3: Integer; var icase:Integer; var izrov, iposv:IVEC);


    implementation


    //Label 3;

    Procedure simp1(var a:MAT; mm:integer; ll:IVEC; nll, iabf: integer; var kp: integer;
    var bmax:double); Forward;
    Procedure simp2(var a:MAT; m, n:integer; l2:IVEC; nl2:integer; var ip:integer;
    kp:integer; var q1:double); Forward;
    Procedure simp3(var a:MAT; i1,k1,ip,kp:integer); Forward;


    Procedure simplx(var a:MAT; m, n, m1, m2, m3: Integer; var icase:Integer; var izrov, iposv:IVEC);



    {-----------------------------------------------------------------------------------------
    USES simp1,simp2,simp3.
    Simplex method for linear programming. Input parameters a, m, n, m1, m2, and m3, and
    output parameters a, icase, izrov, and iposv are described above (see reference).
    Constants: MMAX is the maximum number of constraints expected; NMAX is the maximum number
    of variables expected; EPS is the absolute precision, which should be adjusted to the
    scale of your variables.
    -----------------------------------------------------------------------------------------}
    Label 1,2,10,20,30, return;
    Var
    i,ip,ir,is1,k,kh,kp,m12,nl1,nl2: Integer;
    l1, l2, l3: IVEC;
    bmax,q1,EPS: double;
    Begin

    setlength(l1,n+1);
    setlength(l2,n+1);
    setlength(l3,n+1);

    EPS:=1e-6;
    if m <> m1+m2+m3 then
    begin
    writeln(' Bad input constraint counts in simplx.');
    goto return
    end;
    nl1:=n;
    for k:=1 to n do
    begin
    l1[k]:=k; {Initialize index list of columns admissible for exchange.}
    izrov[k]:=k {Initially make all variables right-hand.}
    end;
    nl2:=m;
    for i:=1 to m do
    begin
    if a[i+1,1] < 0.0 then
    begin
    writeln(' Bad input tableau in simplx, Constants bi must be nonnegative.');
    goto return
    end;
    l2[i]:=i;
    iposv[i]:=n+i {-------------------------------------------------------------------------------------------------
    Initial left-hand variables. m1 type constraints are represented by having their slackv ariable
    initially left-hand, with no artificial variable. m2 type constraints have their slack
    variable initially left-hand, with a minus sign, and their artificial variable handled implicitly
    during their first exchange. m3 type constraints have their artificial variable initially
    left-hand. -------------------------------------------------------------------------------------------------}
    end;
    for i:=1 to m2 do l3[i]:=1;
    ir:=0;
    if m2+m3 = 0 then goto 30; {The origin is a feasible starting solution. Go to phase two.}
    ir:=1;
    for k:=1 to n+1 do {Compute the auxiliary objective function.}
    begin
    q1:=0.0;
    for i:=m1+1 to m do q1 := q1 + a[i+1,k];
    a[m+2,k]:=-q1
    end;
    10: simp1(a,m+1,l1,nl1,0,kp,bmax); {Find max. coeff. of auxiliary objective fn}
    if(bmax <= EPS) and (a[m+2,1] < -EPS) then
    begin
    icase:=-1; {Auxiliary objective function is still negative and can’t be improved,}
    goto return {hence no feasible solution exists.}
    end
    else if (bmax <= EPS) and (a[m+2,1] <= EPS) then
    { Auxiliary objective function is zero and can’t be improved; we have a feasible starting vector.
    Clean out the artificial variables corresponding to any remaining equality constraints by
    goto 1’s and then move on to phase two by goto 30. }
    begin
    m12:=m1+m2+1;
    if m12 <= m then
    for ip:=m12 to m do
    if iposv[ip] = ip+n then {Found an artificial variable for an equalityconstraint.}
    begin
    simp1(a,ip,l1,nl1,1,kp,bmax);
    if bmax > EPS then goto 1; {Exchange with column corresponding to maximum}
    end; {pivot element in row.}
    ir:=0;
    m12:=m12-1;
    if m1+1 > m12 then goto 30;
    for i:=m1+1 to m1+m2 do {Change sign of row for any m2 constraints}
    if l3[i-m1] = 1 then {still present from the initial basis.}
    for k:=1 to n+1 do
    a[i+1,k] := -1.0 * a[i+1,k];
    goto 30 {Go to phase two.}
    end;

    simp2(a,m,n,l2,nl2,ip,kp,q1); {Locate a pivot element (phase one). }

    if ip = 0 then {Maximum of auxiliary objective function is}
    begin {unbounded, so no feasible solution exists.}
    icase:=-1;
    goto return
    end;
    1: simp3(a,m+1,n,ip,kp);
    { Exchange a left- and a right-hand variable (phase one), then update lists.}
    if iposv[ip] >= n+m1+m2+1 then {Exchanged out an artificial variable for an}
    begin {equality constraint. Make sure it stays
    out by removing it from the l1 list. }
    for k:=1 to nl1 do
    if l1[k] = kp then goto 2;
    2: nl1:=nl1-1;
    for is1:=k to nl1 do l1[is1]:=l1[is1+1];
    end
    else
    begin
    if iposv[ip] < n+m1+1 then goto 20;
    kh:=iposv[ip]-m1-n;
    if l3[kh] = 0 then goto 20; {Exchanged out an m2 type constraint.}
    l3[kh]:=0 {If it’s the first time, correct the pivot column or the
    minus sign and the implicit artificial variable. }
    end;
    a[m+2,kp+1] := a[m+2,kp+1] + 1.0;
    for i:=1 to m+2 do a[i,kp+1] := -1.0 * a[i,kp+1];
    20: is1:=izrov[kp]; {Update lists of left- and right-hand variables.}
    izrov[kp]:=iposv[ip];
    iposv[ip]:=is1;
    if ir <> 0 then goto 10; {if still in phase one, go back to 10.
    End of phase one code for finding an initial feasible solution. Now, in phase two, optimize it.}
    30: simp1(a,0,l1,nl1,0,kp,bmax); {Test the z-row for doneness.}
    if bmax <= EPS then {Done. Solution found. Return with the good news.}
    begin
    icase:=0;
    goto return
    end;
    simp2(a,m,n,l2,nl2,ip,kp,q1); {Locate a pivot element (phase two).}
    if ip = 0 then {Objective function is unbounded. Report and return.}
    begin
    icase:=1;
    goto return
    end;
    simp3(a,m,n,ip,kp); {Exchange a left- and a right-hand variable (phase two),}
    goto 20; {update lists of left- and right-hand variables and
    {return for another iteration. }
    return: End;

    {The preceding routine makes use of the following utility subroutines: }

    Procedure simp1(var a:MAT; mm:integer; ll:IVEC; nll, iabf: integer; var kp: integer;
    var bmax:double);
    { Determines the maximum of those elements whose index is contained in the supplied list
    ll, either with or without taking the absolute value, as flagged by iabf. } Label return;
    Var
    k: integer;
    test: double;
    Begin
    kp:=ll[1];
    bmax:=a[mm+1,kp+1];
    if nll < 2 then goto return;
    for k:=2 to nll do
    begin
    if iabf = 0 then
    test:=a[mm+1,ll[k]+1]-bmax
    else
    test:=abs(a[mm+1,ll[k]+1])-abs(bmax);
    if test > 0.0 then
    begin
    bmax:=a[mm+1,ll[k]+1];
    kp:=ll[k]
    end
    end;
    return: End;

    Procedure simp2(var a:MAT; m, n:integer; l2:IVEC; nl2:integer; var ip:integer;
    kp:integer; var q1:double);
    Label 2,6, return;
    Var EPS: double;
    i,ii,k: integer;
    q,q0,qp: double;
    Begin
    EPS:=1e-6;
    { Locate a pivot element, taking degeneracy into account.}
    ip:=0;
    if nl2 < 1 then goto return;
    for i:=1 to nl2 do
    if a[i+1,kp+1] < -EPS then goto 2;
    goto return; {No possible pivots. Return with message.}
    2: q1:=-a[l2[i]+1,1]/a[l2[i]+1,kp+1];
    ip:=l2[i];
    if i+1 > nl2 then goto return;
    for i:=i+1 to nl2 do
    begin
    ii:=l2[i];
    if a[ii+1,kp+1] < -EPS then
    begin
    q:=-a[ii+1,1]/a[ii+1,kp+1];
    if q < q1 then
    begin
    ip:=ii;
    q1:=q
    end
    else if q = q1 then {We have a degeneracy.}
    begin
    for k:=1 to n do
    begin
    qp:=-a[ip+1,k+1]/a[ip+1,kp+1];
    q0:=-a[ii+1,k+1]/a[ii+1,kp+1];
    if q0 <> qp then goto 6
    end;
    6: if q0 < qp then ip:=ii
    end
    end
    end;
    return: End;

    Procedure simp3(var a:MAT; i1,k1,ip,kp:integer);
    { Matrix operations to exchange a left-hand and right-hand variable (see text).}
    Var
    ii,kk:integer;
    piv:double;
    Begin
    piv:=1.0/a[ip+1,kp+1];
    if i1 >= 0 then
    for ii:=1 to i1+1 do
    begin
    if ii-1 <> ip then
    begin
    a[ii,kp+1] := a[ii,kp+1] * piv;
    for kk:=1 to k1+1 do
    if kk-1 <> kp then
    a[ii,kk] := a[ii,kk] - a[ip+1,kk]*a[ii,kp+1]
    end
    end;
    for kk:=1 to k1+1 do
    if kk-1 <> kp then a[ip+1,kk] :=-a[ip+1,kk]*piv;
    a[ip+1,kp+1]:=piv
    End;

    end.


    { end of file tsimplex.pas}

    -----------------------------------------------------------------


    And here is the test program that uses the above unit:


    -------------------------------------------------------------------


    Program test_simplex;

    uses TSimplex;


    Label 3;

    var i,j:integer;

    {main program}
    BEGIN

    writeln;
    write(' Number of variables in E.F.: '); readln(N);
    write(' Number of <= inequalities..: '); readln(M1);
    write(' Number of >= inequalities..: '); readln(M2);
    write(' Number of = equalities.....: '); readln(M3);

    M:=M1+M2+M3; {Total number of constraints}

    setlength(TSimplex.A,m+3,n+2);

    setlength(IPOSV,n+1);
    setlength(IZROV,n+1);

    for i:=1 to M+2 do
    for j:=1 to N+1 do
    TSimplex.A[i,j]:=0.0;

    writeln(' Input Economic Function:');
    for i:=2 to N+1 do
    begin
    write(' Coefficient #',i-1,': ');
    readln(TSimplex.A[1,i])
    end;
    write(' Constant term : ');
    readln(TSimplex.A[1,1]);
    { input constraints }
    for i:=1 to M do
    begin
    writeln(' Input constraint #',i,':');
    for j:=2 to N+1 do
    begin
    write(' Coefficient #',j-1,': ');
    readln(R);
    TSimplex.A[i+1,j] := -R
    end;
    write(' Constant term : ');
    readln(TSimplex.A[i+1,1])
    end;

    writeln;
    writeln(' Input Table:');
    for i:=1 to M+1 do
    begin
    for j:=1 to N+1 do write(TSimplex.A[i,j]:8:2);
    writeln
    end;

    simplx(A,M,N,M1,M2,M3,ICASE,IZROV,IPOSV);

    if ICASE=0 then {result ok.}
    begin
    writeln;
    writeln(' Maximum of E.F. = ', TSimplex.A[1,1]:12:6);

    for i:=1 to N do
    begin
    for j:=1 to M do
    if IPOSV[j] = i then
    begin
    writeln(' X',i,' = ', TSimplex.A[j+1,1]:12:6);
    goto 3;
    end;
    writeln(' X',i,' = ', 0.0:12:6);
    3: end
    end
    else
    writeln(' No solution (error code = ', ICASE,').');

    writeln;


    END.

    --------------------------------------------------------------




    Thank you,
    Amine Moulay Ramdane.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)