Program LINEAR; (* PROGRAM TITLE: Linear Programming ** ** WRITTEN BY: W.M. Yarnall ** 19 Angus Lane ** Warren, N.J. 07060 ** DATE WRITTEN: March 1980 ** ** WRITTEN FOR: S100 MICROSYSTEMS ** MAR 1980 ** ** SUMMARY: Minimize a cost function to constraints. ** Maximize negative of 'profit' function. ** This program uses the Revised Simplex Algorithm. ** ** MODIFICATION RECORD: ** 25 MAY 1980 -MODIFIED FOR PASCAL/Z BY RAYMOND E. PENLEY ** ** ---NOTE--- ** ** The first logical record in Pascal/Z is No.1, NOT record ** No. 0 as in Pascal/M or UCSD Pascal. This can be rectified ** very eaisly by adding a "BIAS" to each record number. ** Pascal/Z : bias = 1 | Pascal/M : bias = 0 ** *) LABEL 99; { File not found exit } CONST maxrow = 32; maxcol = 64; bias = 1; (* Bias added to each record *) FID_LENGTH = 14; (* MAXIMUM LENGTH ALLOWED FOR A FILE NAME *) TYPE FID = STRING FID_LENGTH; ROW = array [1..maxrow] of real; COL = array [1..maxcol] of real; Frec = record CASE TAG : integer of 0: (name : STRING 6; num1, num2 : integer); 1: (header : STRING 64); 2: (Rname : STRING 6; Rindex : integer; RHS : real); 4: (Cname : STRING 6; Cindex : integer; OBJ : real); 6: (R, S : integer; T : real); 99: () {End_Of_File} end; STRING80 = STRING 80; VAR ABAR : array [1..maxrow, 1..maxcol] of real; Colname : array [1..maxcol] of STRING 6; fa : FILE of Frec; (*---File descriptor ---*) File_ID : FID; (*---File Identifier ---*) F : Frec; heading : STRING 64; hdrflag : boolean; list : array [1..maxrow] of integer; M, N, MP, M1 : integer; PNAME : STRING 6; Result : integer; Rowname : array [1..maxrow] of STRING 6; U : array [1..maxrow, 1..maxrow] of real; X,XIK : ROW; PROCEDURE GETID( MESSAGE : STRING80; VAR ID: FID ); (** FID_LENGTH = 14; STRING80 = STRING 80; FID = STRING FID_LENGTH; **) CONST SPACE = ' '; TYPE (*----Required for PASCAL/Z supplied functions----*) STR0 = STRING 0; STR255 = STRING 255; (*----required by PASCAL/Z----*) FUNCTION LENGTH(X: STR255): INTEGER; EXTERNAL; PROCEDURE SETLENGTH(VAR X: STR0; Y: INTEGER); EXTERNAL; begin{GetID} SETLENGTH(ID,0); writeln; write(message); READLN(ID); While Length(ID)M then S := Rowname[I] ; writeln( I:8,' ', S:8, list[I]:7, X[I]:18:8 ) end(*FOR*); writeln end(*---of PRINX---*); Procedure EXITER(exitcode, X : integer); begin CASE exitcode of 1: begin Result := 1; (* Normal exit *) Writeln(' End of Phase 1 for ', Pname, ' after', X:3, ' Iterations'); PRINTX end; 2: begin Result := 2; (* Error exit *) Writeln(' Error in Iteration', X:3); PRINTX end; 3: begin Result := 3; (* No feasible solution *) Writeln(' No feasible solution after', X:3, ' Iterations'); PRINTX end; 4: begin Result := 1; (* Normal exit *) Writeln(' End of Phase 2 for ', Pname, ' after', X:3, ' Iterations'); PRINTX end; 5: begin Result := 2; (* Unbounded solution *) Writeln(' Unbounded solution for ', Pname); PRINTX end end(* CASE exitcode of *) end(*---of EXITER---*); Procedure INITIAL; VAR Rcd, {Record counter} I,J : integer; sum : real; XEOF, {End of File flag for a NON text File} firstin : boolean; B : ROW; C : COL; begin For I:=1 to maxrow do For J:=1 to maxcol do ABAR[I,J] := 0.0 ; firstin := false; Rcd := 0;{start at the beginning} READ(fa:Rcd+bias, F); XEOF := (F.tag=99); If F.tag=0 then begin firstin := true; Pname := F.name; M := F.num1; {No. Rows} N := F.num2; {No. Columns} MP := M + 2; M1 := M + 1; PRINTH end(* IF *) Else begin writeln; writeln(' Bad file format'); writeln; Result := 2 end(* ELSE *); While (firstin) AND (NOT XEOF) do begin With F do CASE TAG of 1: begin(* heading *) heading := header; hdrflag := true end; 2: begin(* row_name & RHS *) Rowname[Rindex] := Rname; B[Rindex] := RHS end; 4: begin(* col_name & OBJ *) Colname[Cindex] := Cname; C[Cindex] := OBJ end; 6: ABAR[R,S] := T; 99: (* NULL *) End{With/Case}; Rcd := Rcd + 1; READ(fa:Rcd+bias, F); XEOF := (F.tag=99); end(* While *); If firstin then begin PRINTC(B,C); For J:=1 to N do ABAR[M1,J] := C[J]; For I:=1 to M do If B[I]<0.0 then begin B[I] := -B[I]; For J:=1 to N do ABAR[I,J] := -ABAR[I,J] end; For J:=1 to N do begin SUM := 0.0; For I:=1 to M do SUM := SUM - ABAR[I,J]; ABAR[MP,J] := SUM end; B[M1] := 0.0; SUM := 0.0; For I:=1 to M do SUM := SUM - B[I]; B[MP] := SUM; For I:=1 to MP do begin X[I] := B[I]; list[I] := N +I; For J:=1 to MP do U[I,J] := 0.0 end; For I:=1 to MP do U[I,I] := 1.0; PRINTD; Rowname[M1] := 'M+1 '; Rowname[MP] := 'M+2 '; PRINTX end(* If firstin *); Writeln end(*---of INITIAL---*); Procedure PHASE1; LABEL 304; (* Exit point *) CONST TOL = 1.0E-5; VAR iter, I, J, L, ksave : integer; sum, temp, theta, Z : real; XL, XLK : real; DEL, V, W : ROW; test : boolean; begin writeln(' Start Phase 1'); writeln; iter := 0; While true do begin If ABS(X[MP])tol then {error exit} begin EXITER(2,iter); goto 304 end; iter := iter +1; For J:=1 to N do begin SUM := 0.0; For I:=1 to MP do SUM := SUM + U[MP,I] * ABAR[I,J]; DEL[J] := SUM end; test := true; For J:=1 to N do If DEL[J]<0.0 then test := false; If test then {no feasible solution exit} begin EXITER(3,iter); goto 304 end; temp := 1.0E+36; ksave := 0; For J:=1 to N do If DEL[J]0.0 then begin Z := X[I] / XIK[I]; If (Z=theta) AND (list[I]>N) then L := I Else If Zksave) then Z := X[I] - XL * V[I]; X[I] := Z; For J:=1 to M do begin Z := W[J] / XLK; If I<>L then Z := U[I,J] - W[J] * V[I]; U[I,J] := Z end end; writeln(' Iteration', iter:3, ' of ', Pname); PRINTX end(* While true *); 304: (* Exit point *) end(*---of PHASE1---*); Procedure PHASE2; LABEL 403; (* Exit point *) CONST TOL = -1.0E-5; VAR I, J, L, iter, ksave : integer; SUM, temp, theta, Z : real; XL, XLK : real; DEL, V, W : ROW; test : boolean; begin iter := 0; writeln(' Start Phase 2'); writeln; While true do begin For J:=1 to N do begin SUM := 0.0; For I:=1 to MP do SUM := SUM + U[M1,I] * ABAR[I,J]; DEL[J] := SUM end; test := true; For J:=1 to N do If DEL[J]0.0 then test := false; If test then begin EXITER(5,iter); goto 403 end; theta := 1.0E+36; L := 0; For I:=1 to M do If XIK[I]>0.0 then begin Z := X[I] / XIK[I]; If Zksave) then Z := X[I] - XL * V[I]; X[I] := Z; For J:=1 to M do begin Z := W[J] / XLK; If I<>L then Z := U[I,J] - W[J] * V[I]; U[I,J] := Z end end; writeln(' Iteration', iter:3, ' of ', Pname); PRINTX; end(* While true *); 403: (* Exit point *) end(*---of PHASE2---*); Procedure CLEAR; (* simple screen clear routine *) VAR ix : 1..25; begin for ix:=1 to 25 do writeln end; BEGIN (*** MAIN PROGRAM ***) CLEAR; GETID(' Enter data File Name ---> ', File_ID); RESET(File_ID, fa); (*---RESET( , )---*) If EOF(fa) then begin Writeln(CHR(7),'File ',File_ID,'not found'); {exit}goto 99 end; Writeln; INITIAL; If Result<>2 then PHASE1; If Result=1 then PHASE2; If hdrflag then Writeln(' ', heading); 99: {File not found exit}; Writeln;Writeln;Writeln;Writeln;Writeln end(*---of Linear---*). .