{$A+,B-,D-,E+,F-,I-,L-,N-,O-,R-,S-,V-}
{$M 20000,0,600000}
PROGRAM PO;
  { este programa implementa os seguintes metodos para resolucao de
    problemas de programacao linear:
    - simplex primeira fase
    - full simplex
    - revised simplex
    - dual simplex
    e ainda o algoritmo de Gomory para programacao linear inteira

    Autor:Glauber Cintra }

USES CRT,ROTTELA;

CONST FWT=7;
      DEC=2;
      FWI=1;
      MAIORVALOR=1.0E20;
      MENORVALOR=1.0E-8;
      MAXRES = 49;
      MAXVAR = 3*MAXRES;

TYPE RESRANGE = 1..MAXRES;
     VARRANGE = 1..MAXVAR;
     MATRIZ = ARRAY [RESRANGE,VARRANGE] OF REAL;
     COLUNA = ARRAY [RESRANGE] OF REAL;
     BASEINDECE = ARRAY [RESRANGE] OF BYTE;
     LINHA = ARRAY [VARRANGE] OF REAL;
     LINHALOGICO = ARRAY [VARRANGE] OF BOOLEAN;
     MSQUARE = ARRAY [RESRANGE,RESRANGE] OF REAL;
     FASE = (FASEI, FASEII);
     SIGNAL = ARRAY [RESRANGE] OF CHAR;
     VARIAVEL = ARRAY [VARRANGE] OF STRING[6];

VAR A : MATRIZ;
    Z0,W0 : REAL;
    IT : INTEGER;
    SINAL : SIGNAL;
    BETA : MSQUARE;
    NOME : VARIAVEL;
    C,D,FOLGA : LINHA;
    TECLA,OPCAO : CHAR;
    BASICA : BASEINDECE;
    NAOBASICA : LINHALOGICO;
    B,BDASH,PI,SIGMA : COLUNA;
    TELA,TELAORIGINAL : PONT_TELA;
    SOLUCAO,ILIMITADA,OK,TABLEAU,PARADA : BOOLEAN;
    IMPOSSIVEL,PPL,PRIMAL,IMPRESS,PRIMEIRO : BOOLEAN;
    R,S,GC,EC,LC,N1,N2,M,NUMVAR,I,J,POSX,POSY : BYTE;
    GCPLUSLC,GCPLUSC,GCPLUSEC,BESQ,BDIR,CORIG,CINIC : BYTE;

FUNCTION CARACTERE(VALOR : REAL) : STRING;
   VAR I : BYTE;
       J,K,L : STRING;
       NAOZERO : BOOLEAN;
   BEGIN
   NAOZERO:=FALSE;
   STR(VALOR:20:6,K);
   J:='';
   L:='';
   FOR I:=1 TO 13 DO
      IF K[I]<>' ' THEN
         L:=L+K[I];
   FOR I:=20 DOWNTO 15 DO
      BEGIN
      IF K[I]<>'0' THEN
         NAOZERO:=TRUE;
      IF NAOZERO THEN
         J:=K[I]+J
      END;
   IF J='' THEN
      CARACTERE:=L
      ELSE
      CARACTERE:=L+'.'+J
   END;

PROCEDURE INPUTDATA(VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA;VAR NRES,NUMVAR:BYTE);
   CONST ERROS : ARRAY [1..7] OF STRING[50] = ('Nome de vari vel inv lido',
         'Operador aritm‚tico repetido','Vari vel esperada',
         'Operador relacional incorreto','Lado direito incorreto',
         'Caractere inv lido','Lado direito incompleto');
   VAR I,J : BYTE;
       K : CHAR;
       SAVENUMVAR,SAVENRES,ERRO : BYTE;
       SAVEB : REAL;
       SAVESINAL : CHAR;
       SAVENOME : VARIAVEL;
       SAVEA : LINHA;
       RESTRICAO : STRING;

   FUNCTION PROCURA_VARIAVEL(NOMEVAR : STRING) : BYTE;
      VAR I : BYTE;
      BEGIN
      I:=1;
      WHILE (NOME[I]<>NOMEVAR) AND (I<=NUMVAR) DO
         INC(I);
      IF I>MAXRES THEN
         BEGIN
         WRITELN('N£mero de vari veis maior que o permitido. (',maxres,')');
         WRITELN(CHR(7),'Execu‡„o cancelada.');
         HALT
         END;
      PROCURA_VARIAVEL:=I
      END;

   PROCEDURE ANALISAOBJ(VAR CADEIA : STRING;VAR C : LINHA;
                        VAR NOME : VARIAVEL;VAR NVAR,ERRO : BYTE);
      VAR PALAVRA,ESTADO : STRING;
          LETRA : CHAR;
          I,TAMANHO,INDICE: BYTE;
          COEFICIENTE : REAL;
          AUX : INTEGER;
      BEGIN
      PALAVRA:='';
      LETRA:=' ';
      ESTADO:='OPERADOR';
      TAMANHO:=LENGTH(CADEIA);
      ERRO:=0;
      FOR I:=1 TO TAMANHO DO
         BEGIN
         LETRA:=CADEIA[I];
         CASE LETRA OF
         'A'..'Z','a'..'z','_' :
            BEGIN
            IF ESTADO='VARIAVEL' THEN
               PALAVRA:=PALAVRA+LETRA
               ELSE
               IF (ESTADO='OPERADOR') OR (ESTADO='NUMERO') THEN
                  BEGIN
                  IF (PALAVRA='') OR (PALAVRA='+')
                     THEN
                     COEFICIENTE:=1
                     ELSE
                     IF PALAVRA='-' THEN
                        COEFICIENTE:=-1
                        ELSE
                        VAL(PALAVRA,COEFICIENTE,AUX);
                  ESTADO:='VARIAVEL';
                  PALAVRA:=LETRA
                  END;
            END;

         '0'..'9','.' :
            BEGIN
            IF ESTADO='NUMERO' THEN
               PALAVRA:=PALAVRA+LETRA
               ELSE
               IF (ESTADO='VARIAVEL') AND (LETRA<>'.') THEN
                  PALAVRA:=PALAVRA+LETRA
                  ELSE
                  IF ESTADO='OPERADOR' THEN
                     BEGIN
                     PALAVRA:=PALAVRA+LETRA;
                     ESTADO:='NUMERO'
                     END
                     ELSE
                     ERRO:=1;
            END;

         '+','-' :
            BEGIN
            IF ESTADO='OPERADOR' THEN
               IF PALAVRA='' THEN
                  PALAVRA:=LETRA
                  ELSE
                  ERRO:=2
               ELSE
               IF ESTADO='NUMERO' THEN
                  ERRO:=3
                  ELSE
                  IF ESTADO='VARIAVEL' THEN
                     BEGIN
                     ESTADO:='OPERADOR';
                     INDICE:=PROCURA_VARIAVEL(PALAVRA);
                     NOME[INDICE]:=PALAVRA;
                     C[INDICE]:=C[INDICE]+COEFICIENTE;
                     IF INDICE>NVAR THEN
                        NVAR:=INDICE;
                     PALAVRA:=LETRA
                     END;
            END;

         ' ' :
         ELSE
            ERRO:=6;
         END;
         IF ERRO<>0 THEN
            I:=TAMANHO;
         END;
      IF ERRO=0 THEN
         IF ESTADO='VARIAVEL' THEN
            BEGIN
            INDICE:=PROCURA_VARIAVEL(PALAVRA);
            IF INDICE>NVAR THEN
               NVAR:=INDICE;
            NOME[INDICE]:=PALAVRA;
            C[INDICE]:=C[INDICE]+COEFICIENTE
            END
            ELSE
            ERRO:=3
      END;

   PROCEDURE ANALISA(VAR CADEIA : STRING;VAR A : MATRIZ;VAR B:COLUNA;
             VAR SINAL : SIGNAL;VAR NOME : VARIAVEL;VAR NVAR,NRES,ERRO : BYTE);
      VAR PALAVRA,ESTADO : STRING;
          LETRA : CHAR;
          I,TAMANHO,INDICE: BYTE;
          JAOPREL : BOOLEAN;
          COEFICIENTE : REAL;
          AUX : INTEGER;
      BEGIN
      JAOPREL:=FALSE;
      PALAVRA:='';
      LETRA:=' ';
      ESTADO:='OPERADOR';
      TAMANHO:=LENGTH(CADEIA);
      ERRO:=0;
      FOR I:=1 TO TAMANHO DO
         BEGIN
         LETRA:=CADEIA[I];
         CASE LETRA OF
         'A'..'Z','a'..'z','_' :
            BEGIN
            IF JAOPREL THEN
               ERRO:=5
               ELSE
               IF ESTADO='VARIAVEL' THEN
                  PALAVRA:=PALAVRA+LETRA
                  ELSE
                  IF ESTADO='OPREL' THEN
                     ERRO:=5
                     ELSE
                     IF (ESTADO='OPERADOR') OR (ESTADO='NUMERO') THEN
                        BEGIN
                        IF (PALAVRA='') OR (PALAVRA='+')
                           THEN
                           COEFICIENTE:=1
                           ELSE
                           IF PALAVRA='-' THEN
                              COEFICIENTE:=-1
                              ELSE
                              VAL(PALAVRA,COEFICIENTE,AUX);
                        ESTADO:='VARIAVEL';
                        PALAVRA:=LETRA
                        END;
            END;

         '0'..'9','.' :
            BEGIN
            IF ESTADO='NUMERO' THEN
               PALAVRA:=PALAVRA+LETRA
               ELSE
               IF (ESTADO='VARIAVEL') AND (LETRA<>'.') THEN
                  PALAVRA:=PALAVRA+LETRA
                  ELSE
                  IF ESTADO='OPREL' THEN
                     BEGIN
                     ESTADO:='NUMERO';
                     IF PALAVRA[1]='=' THEN
                        SINAL[NRES]:='='
                        ELSE
                        IF PALAVRA[1]='>' THEN
                           SINAL[NRES]:='ò'
                           ELSE
                           SINAL[NRES]:='ó';
                     JAOPREL:=TRUE;
                     PALAVRA:=LETRA
                     END
                     ELSE
                     IF ESTADO='OPERADOR' THEN
                        BEGIN
                        PALAVRA:=PALAVRA+LETRA;
                        ESTADO:='NUMERO'
                        END
                        ELSE
                        ERRO:=1;
            END;

         '+','-' :
            BEGIN
            IF ESTADO='OPERADOR' THEN
               IF PALAVRA='' THEN
                  PALAVRA:=LETRA
                  ELSE
                  ERRO:=2
               ELSE
               IF ESTADO='OPREL' THEN
                  BEGIN
                  IF PALAVRA[1]='=' THEN
                     SINAL[NRES]:='='
                     ELSE
                     IF PALAVRA[1]='>' THEN
                        SINAL[NRES]:='ò'
                        ELSE
                        SINAL[NRES]:='ó';
                  ESTADO:='OPERADOR';
                  JAOPREL:=TRUE;
                  PALAVRA:=LETRA
                  END
                  ELSE
                  IF ESTADO='NUMERO' THEN
                     ERRO:=3
                     ELSE
                     IF ESTADO='VARIAVEL' THEN
                        BEGIN
                        ESTADO:='OPERADOR';
                        INDICE:=PROCURA_VARIAVEL(PALAVRA);
                        NOME[INDICE]:=PALAVRA;
                        A[NRES,INDICE]:=A[NRES,INDICE]+COEFICIENTE;
                        IF INDICE>NVAR THEN
                           NVAR:=INDICE;
                        PALAVRA:=LETRA
                        END;
            END;

         '>','<','=' :
            BEGIN
            IF JAOPREL THEN
               ERRO:=4
               ELSE
               IF ESTADO='OPREL' THEN
                  IF ((LETRA='=') AND (PALAVRA='=')) OR (LENGTH(PALAVRA)>2) THEN
                     ERRO:=4
                     ELSE
                     PALAVRA:=PALAVRA+LETRA
                  ELSE
                  IF (ESTADO='OPERADOR') OR (ESTADO='NUMERO') THEN
                     ERRO:=3
                     ELSE
                     BEGIN
                     ESTADO:='OPREL';
                     INDICE:=PROCURA_VARIAVEL(PALAVRA);
                     IF INDICE>NVAR THEN
                        NVAR:=INDICE;
                     NOME[INDICE]:=PALAVRA;
                     A[NRES,INDICE]:=A[NRES,INDICE]+COEFICIENTE;
                     PALAVRA:=LETRA
                     END;
            END;
         ' ' :
         ELSE
            ERRO:=6;
         END;
         IF ERRO<>0 THEN
            I:=TAMANHO;
         END;
      IF ERRO=0 THEN
         IF JAOPREL THEN
            VAL(PALAVRA,B[NRES],AUX)
            ELSE
            IF ESTADO='VARIAVEL' THEN
               BEGIN
               ERRO:=8;
               INDICE:=PROCURA_VARIAVEL(PALAVRA);
               IF INDICE>NVAR THEN
                  NVAR:=INDICE;
               NOME[INDICE]:=PALAVRA;
               A[NRES,INDICE]:=A[NRES,INDICE]+COEFICIENTE
               END
               ELSE
               ERRO:=3
      END;

   BEGIN
   FOR I:=1 TO MAXRES DO
      FOR J:=1 TO MAXVAR DO
         A[I,J]:=0;
   FOR I:=1 TO MAXVAR DO
      C[I]:=0;
   GC:=0;
   LC:=0;
   EC:=0;
   RESTRICAO:=' ';
   NRES:=1;
   NUMVAR:=0;
   ERRO:=1;
   WRITELN('Fun‡„o Objetivo :');
   WHILE ERRO<>0 DO
      BEGIN
      WRITE('Min ');
      READLN(RESTRICAO);
      SAVEA:=C;
      SAVENOME:=NOME;
      SAVENUMVAR:=NUMVAR;
      ANALISAOBJ(RESTRICAO,C,NOME,NUMVAR,ERRO);
      IF ERRO<>0 THEN
         BEGIN
         C:=SAVEA;
         NOME:=SAVENOME;
         NUMVAR:=SAVENUMVAR;
         WRITELN(ERROS[ERRO])
         END;
      END;
   WRITELN;
   RESTRICAO:=' ';
   WHILE RESTRICAO<>'' DO
      BEGIN
      ERRO:=1;
      WHILE (ERRO<>0) AND (RESTRICAO<>'') DO
         BEGIN
         WRITE('Restri‡„o ',NRES,' : ');
         READLN(RESTRICAO);
         IF RESTRICAO<>'' THEN
            BEGIN
            SAVENUMVAR:=NUMVAR;
            SAVENRES:=NRES;
            SAVENOME:=NOME;
            SAVESINAL:=SINAL[NRES];
            SAVEB:=B[NRES];
            FOR I:=1 TO MAXVAR DO
               SAVEA[I]:=A[NRES,I];
            ANALISA(RESTRICAO,A,B,SINAL,NOME,NUMVAR,NRES,ERRO);
            IF ERRO=0 THEN
               BEGIN
               IF SINAL[NRES]='ò' THEN
                  INC(GC)
                  ELSE
                  IF SINAL[NRES]='ó' THEN
                     INC(LC)
                     ELSE
                     INC(EC);
               INC(NRES)
               END
               ELSE
               IF ERRO<>8 THEN
                  BEGIN
                  NUMVAR:=SAVENUMVAR;
                  NRES:=SAVENRES;
                  B[NRES]:=SAVEB;
                  SINAL[NRES]:=SAVESINAL;
                  FOR I:=1 TO MAXVAR DO
                     A[NRES,I]:=SAVEA[I];
                  NOME:=SAVENOME;
                  WRITELN(ERROS[ERRO])
                  END;
            END;
         END;
      END;
   PPL:=FALSE;
   IF NRES>1 THEN
      PPL:=TRUE;
   PRIMAL:=TRUE;
   FOR I:=1 TO NRES DO
      IF (SINAL[I]='=') OR (SINAL[I]='ò') THEN
         PRIMAL:=FALSE;
   NRES:=NRES-1
   END;

PROCEDURE INITIALISE(VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
   VAR I,J,K : BYTE;
   BEGIN
   IT:=0;
   Z0:=0.0;
   OK:=TRUE;
   GCPLUSLC:=GC+LC;
   GCPLUSEC:=GC+EC;
   N1 := NUMVAR + GCPLUSLC + GCPLUSEC;
   N2 := NUMVAR + GCPLUSLC;
   SOLUCAO:=FALSE;
   ILIMITADA:=FALSE;
   IMPOSSIVEL:=FALSE;
   K:=M*FWT;
   IF K<18 THEN
      K:=18;
   BDIR := (K-16) DIV 2;
   BESQ := K-16-BDIR
   END;

PROCEDURE COMPLETETABLEAU(VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
   VAR I,J,K: BYTE;
       SUM: REAL;
   BEGIN
   J:=1;
   K:=1;
   FOR I:=1 TO M DO
      IF SINAL[I]='ò' THEN
         BEGIN
         A[I,NUMVAR+K]:=-1;
         INC(K)
         END
         ELSE
         IF SINAL[I]='ó' THEN
            BEGIN
            A[I,NUMVAR+K]:=1;
            BASICA[J]:=NUMVAR+K;
            INC(J);
            INC(K)
            END;
   FOR I:=1 TO M DO
      IF (SINAL[I]='=') OR (SINAL[I]='ò') THEN
         BEGIN
         A[I,NUMVAR+K]:=1;
         BASICA[J]:=NUMVAR+K;
         INC(J);
         INC(K)
         END;
   FOR J:= 1 TO N1 DO
      NAOBASICA[J]:= TRUE;
   FOR I:= 1 TO M DO
      NAOBASICA[BASICA[I]]:= FALSE;
   FOR J:= 1 TO N2 DO
     BEGIN
     SUM:= 0.0;
     FOR I:= 1 TO M DO
        IF (SINAL[I]='=') OR (SINAL[I]='ò') THEN
           SUM:= SUM + A[I,J];
     D[J]:= -SUM
   END;
   SUM:= 0.0;
   FOR J:= N2+1 TO N1 DO
      D[J]:= 0.0;
   FOR I:= 1 TO M DO
      IF (SINAL[I]='=') OR (SINAL[I]='ò') THEN
         SUM:= SUM + B[I];
   W0:= -SUM
   END;

PROCEDURE OUTPUTTABLEAU(P: FASE;VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
   VAR I,J,N: BYTE;
   BEGIN
   IF P= FASEI THEN
      N:= N1
      ELSE
      N:= N2;
   WRITELN;
   WRITELN('     Itera‡„o ', IT:2);
   IF TABLEAU THEN
      BEGIN
      WRITE('  Var. B sica   ');
      FOR J:= 1 TO N DO
         IF J<=N2 THEN
            WRITE(' ':FWT - FWI - 1,'X', J:FWI)
            ELSE
            WRITE(' ':FWT-FWI-1,'A',J:FWI);
      WRITELN('  Valor');
      FOR I:= 1 TO M DO
         BEGIN
         IF BASICA[I]>N2 THEN
            WRITE(' ':8-FWI,'A',BASICA[I]:FWI,' ':7)
            ELSE
            WRITE(' ':8-FWI,'X', BASICA[I]:FWI,' ':7);
         FOR J:= 1 TO N DO
            WRITE(A[I,J]:FWT:DEC);
         WRITELN(B[I]:FWT:DEC);
         END;
      WRITE(' ':7,'-Z',' ':7);
      FOR J:= 1 TO N DO
         WRITE(C[J]:FWT:DEC);
      WRITELN(Z0:FWT:DEC);;
      IF P = FASEI THEN
         BEGIN
         WRITE(' ':7,'-W',' ':7);
         FOR J:= 1 TO N DO
            WRITE(D[J]:FWT:DEC);
         WRITELN(W0:FWT:DEC)
         END;
      IF PARADA THEN
         TECLA:=READKEY;
      END;
   END;

PROCEDURE NEXTBASICAVARIABLE(VAR R,S,N:BYTE;VAR A:MATRIZ;VAR B:COLUNA;
                                  VAR C:LINHA);
   VAR I,J : BYTE;
       MIN: REAL;
   BEGIN
   MIN:= MAIORVALOR;
   FOR J:= 1 TO N DO
      IF NAOBASICA[J] THEN
         IF C[J]<MIN THEN
            BEGIN
            MIN:= C[J];
            S:= J
            END;
   SOLUCAO := C[S] > -MENORVALOR;
   IF NOT SOLUCAO THEN
      BEGIN
      ILIMITADA:= TRUE; I:= 1;
      WHILE ILIMITADA AND (I<=M) DO
         BEGIN
         ILIMITADA:= A[I,S] < MENORVALOR;
         I:= I + 1
         END;
      IF NOT ILIMITADA THEN
         BEGIN
         MIN:= MAIORVALOR;
         FOR I:= 1 TO M DO
            IF A[I,S] > MENORVALOR THEN
               IF B[I]/A[I,S] < MIN THEN
                  BEGIN
                  MIN:= B[I]/A[I,S];
                  R:= I
                  END;
         NAOBASICA[BASICA[R]]:= TRUE;
         NAOBASICA[S]:= FALSE;
         BASICA[R]:= S;
         WRITELN;
         WRITELN('  Piv“ est  na linha ', R:FWI, ' coluna ', S:FWI)
         END;
      END;
   END;

PROCEDURE NEXTBASICAVARIABLE1(VAR N,R,S:BYTE;VAR A:MATRIZ;VAR B:COLUNA;
                                  VAR C:LINHA);
   VAR I,J : BYTE;
       MIN: REAL;
   BEGIN
   MIN:= MAIORVALOR;
   FOR J := 1 TO N DO
      IF NAOBASICA[J] THEN
         IF C[J]<MIN THEN
            BEGIN
            MIN:= C[J];
            S := J
            END;
   SOLUCAO := C[S] > - MENORVALOR;
   IF NOT SOLUCAO THEN
      BEGIN
      ILIMITADA := TRUE;
      I := 1;
      WHILE ILIMITADA AND (I<=M) DO
         BEGIN
         ILIMITADA := A[I,S] < MENORVALOR;
         I:= I + 1
         END;
      IF NOT ILIMITADA THEN
         BEGIN
         MIN:= MAIORVALOR;
         FOR I := 1 TO M DO
            IF A[I,S] > MENORVALOR THEN
               IF B[I]/A[I,S] < MIN THEN
                  BEGIN
                  MIN:= B[I]/A[I,S];
                  R := I
                  END;
         END;
      END
      ELSE
      BEGIN
      MIN:= MAIORVALOR;
      FOR I := 1 TO M DO
         IF B[I] <= MIN THEN
            BEGIN
            MIN:= B[I];
            R := I
            END;
      SOLUCAO := B[R] > MENORVALOR;
      IF NOT SOLUCAO THEN
         BEGIN
         MIN:= -MAIORVALOR;
         FOR J := 1 TO N DO
         IF NAOBASICA[J] THEN
            IF A[R,J] < -MENORVALOR THEN
               IF C[J]/A[R,J] > MIN THEN
                  BEGIN
                  MIN:= C[J]/A[R,J];
                  S := J
                  END;
         IMPOSSIVEL := MIN< -MAIORVALOR + MENORVALOR
         END;
      END;
   IF NOT (SOLUCAO OR ILIMITADA OR IMPOSSIVEL) THEN
      BEGIN
      NAOBASICA[BASICA[R]] := TRUE;
      NAOBASICA[S] := FALSE;
      BASICA[R]:=S;
      WRITELN;
      WRITELN('   Piv“ est  na linha ',R:FWI,' coluna ',S:FWI)
      END;
  END;

PROCEDURE TRANSFORMTABLEAU(R,S,N:BYTE;P:FASE;VAR A:MATRIZ;
                            VAR B:COLUNA;VAR C:LINHA);
   VAR I,J: BYTE;
       PIVOT, SAVEC, SAVED : REAL;
       SAVECOL: COLUNA;
   BEGIN
   FOR I:= 1 TO M DO
      SAVECOL[I]:= A[I,S];
   PIVOT:= A[R,S];
   FOR J:= 1 TO N DO
      A[R,J]:= A[R,J]/PIVOT;
   B[R]:=B[R]/PIVOT;
   FOR I:= 1 TO M DO
      IF I<>R THEN
         BEGIN
         FOR J:= 1 TO N DO
            A[I,J] := A[I,J] - (SAVECOL[I]*A[R,J]);
         B[I] := B[I] - (SAVECOL[I]*B[R])
         END;
   SAVEC:=C[S];
   FOR J:= 1 TO N DO
      C[J]:= C[J] - SAVEC*A[R,J];
   Z0:= Z0 - SAVEC*B[R];
   IT:= IT + 1;
   IF P = FASEI THEN
      BEGIN
      SAVED:= D[S];
      FOR J:= 1 TO N DO
          D[J]:= D[J] - SAVED*A[R,J];
      W0:= W0 - SAVED*B[R]
      END
   END;

PROCEDURE SIMPLEX(P: FASE;VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
   VAR N : BYTE;
       ILIMITADA: BOOLEAN;
   BEGIN
   SOLUCAO:= FALSE;
   ILIMITADA:= FALSE;
   IF P = FASEI THEN
      N:= N1
      ELSE
      N:= N2;
   REPEAT
      OUTPUTTABLEAU(P,A,B,C);
      CASE P OF
         FASEI  : NEXTBASICAVARIABLE(R,S,N,A,B,D);
         FASEII : NEXTBASICAVARIABLE(R,S,N,A,B,C);
         END;
      IF NOT (SOLUCAO OR ILIMITADA) THEN
         TRANSFORMTABLEAU(R,S,N,P,A,B,C);
      UNTIL SOLUCAO OR ILIMITADA;
   IF ILIMITADA THEN
      WRITELN('   Solu‡„o ilimitada');
   END;

FUNCTION POSFRAC (X:REAL):REAL;
   VAR Y:REAL;
   BEGIN
   IF ABS(X-ROUND(X))<MENORVALOR THEN
      POSFRAC:=0
      ELSE
      BEGIN
      Y:= ABS(X-TRUNC(X));
      IF X>=0.0 THEN
         POSFRAC:=Y
         ELSE
         POSFRAC:=1-Y
      END
   END;

PROCEDURE ADDCONSTRAINT(K:BYTE;VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
   VAR I,J :BYTE;
   BEGIN
   M:=M+1;
   N2:=N2+1;
   NAOBASICA[N2]:=FALSE;
   BASICA[M]:=N2;
   B[M]:= -POSFRAC(B[K]);
   A[M,N2]:=1.0;
   C[N2]:=0.0;
   FOR J:=1 TO N2-1 DO
     IF NAOBASICA[J] THEN
        A[M,J] := -POSFRAC(A[K,J])
        ELSE
        A[M,J]:=0.0;
   FOR I:=1 TO M-1 DO
      A[I,N2]:=0.0;
   IT:=IT +1
   END;

FUNCTION INTEGERSOLUCAO(VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA): BOOLEAN;
   VAR I:BYTE;
       STILLINTEGER: BOOLEAN;
   BEGIN
   I:=0;
   STILLINTEGER:= TRUE;
   WHILE (I<M) AND STILLINTEGER DO
      BEGIN
      I:=I+1;
      IF POSFRAC(B[I]) > MENORVALOR THEN
         BEGIN
         ADDCONSTRAINT(I,A,B,C);
         STILLINTEGER:=FALSE
         END
      END;
   INTEGERSOLUCAO := STILLINTEGER;
   END;

PROCEDURE SIMPLEXMOD (P:FASE;VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
   VAR N : BYTE;
       ILIMITADA, IMPOSSIVEL : BOOLEAN;
   BEGIN
   SOLUCAO := FALSE;
   ILIMITADA:=FALSE;
   IMPOSSIVEL:=FALSE;
   IF P=FASEI THEN
      N:=N1
      ELSE
      N:=N2;
   REPEAT
      OUTPUTTABLEAU(P,A,B,C);
      CASE P OF
         FASEI : NEXTBASICAVARIABLE1(N,R,S,A,B,D);
         FASEII : NEXTBASICAVARIABLE1(N,R,S,A,B,C);
         END;
      IF NOT (SOLUCAO OR ILIMITADA OR IMPOSSIVEL) THEN
         TRANSFORMTABLEAU(R,S,N,P,A,B,C);
      UNTIL SOLUCAO OR ILIMITADA OR IMPOSSIVEL;
   IF ILIMITADA THEN
      WRITELN('    Ilimitada')
      ELSE
      IF IMPOSSIVEL THEN
         WRITELN('    Nenhuma solu‡„o Poss¡vel')
   END;

PROCEDURE PRIMALSIMPLEX(A : MATRIZ;B : COLUNA;C : LINHA);
   BEGIN
   INITIALISE(A,B,C);
   COMPLETETABLEAU(A,B,C);
   WRITELN('     M�TODO SIMPLEX - PRIMEIRA FASE');
   WRITELN;
   REPEAT
      OUTPUTTABLEAU(FASEII,A,B,C);
      NEXTBASICAVARIABLE(R,S,N1,A,B,C);
      IF NOT (SOLUCAO OR ILIMITADA) THEN
         TRANSFORMTABLEAU(R,S,N1,FASEII,A,B,C);
      UNTIL SOLUCAO OR ILIMITADA;
   WRITELN;
   IF ILIMITADA THEN
      WRITELN('   Vari vel X',S:FWI,' ‚ ilimitada')
      ELSE
      WRITELN('   M¡nimo : Z = ',-Z0:FWT:DEC);
   WRITELN
   END;

PROCEDURE FULLSIMPLEX(A : MATRIZ;B : COLUNA;C : LINHA);
   BEGIN
   INITIALISE(A,B,C);
   COMPLETETABLEAU(A,B,C);
   WRITELN('     M�TODO FULL SIMPLEX ');
   WRITELN;
   IF GCPLUSEC = 0 THEN
      WRITELN('    N„o ‚ necess ria fase 1')
      ELSE
      BEGIN
      WRITELN('     FASE 1');
      SIMPLEX(FASEI,A,B,C);
      WRITELN;
      IF (ABS(W0)>MENORVALOR) OR (NOT SOLUCAO) THEN
         BEGIN
         OK:= FALSE;
         WRITELN('     Fase 1 n„o completada');
         WRITELN('     Soma das vari veis artificiais ',W0:FWT:DEC);
         WRITELN('     N„o existe solu‡„o vi vel para este PPL')
         END
         ELSE
         BEGIN
         WRITELN;
         WRITELN('  Fase 1 bem sucedida');
         WRITELN;
         WRITELN('     Tableau reduzido para fase 2')
         END
      END;
   IF OK THEN
      BEGIN
      SIMPLEX(FASEII,A,B,C);
      WRITELN;
      IF NOT SOLUCAO THEN
         WRITELN('     Fase 2 n„o completada.')
         ELSE
         BEGIN
         WRITELN('     Solu‡„o Final ');
         WRITELN;
         WRITELN('     M¡nimo de Z = ', -Z0:FWT:DEC);
         WRITELN;
         WRITELN('     Restri‡„o    Base     Valor    Estado       Folga');
         FOR I:= 1 TO M DO
            FOLGA[BASICA[I]]:= B[I];
         FOR I:= 1 TO M DO
            BEGIN
            WRITE(' ':9,I,' ':9,'X',BASICA[I],' ':11-FWT,B[I]:FWT:DEC,' ':5);
            IF (I<=GC) OR (I>GCPLUSEC) THEN
               IF NAOBASICA[NUMVAR+1] THEN
                  WRITELN('Excesso',0.0:10:DEC)
                  ELSE
                  WRITELN('Folga',' ':12-FWT,FOLGA[NUMVAR+1]:FWT:DEC)
               ELSE
               WRITELN('Nenhuma   equa‡„o');
            END
         END
       END;
   WRITELN
   END;

PROCEDURE SIMPLEXREVISADO(A : MATRIZ;B : COLUNA;C : LINHA);

   PROCEDURE SETVALUES(VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
      VAR I, J : BYTE;
      BEGIN
      FOR J:=1 TO GCPLUSEC DO
         SIGMA[J]:=-1.0;
      FOR J:=GCPLUSEC+1 TO GCPLUSEC+LC DO
         SIGMA[J]:=0.0;
      FOR I:=1 TO M DO
         BETA[I,I]:=1.0;
      FOR J:=1 TO N2 DO
         D[J]:=0.0;
      FOR J:=N2+1 TO N1 DO
         D[J]:=1.0;
      FOR J:=1 TO M DO
         BDASH[J]:=B[J]
      END;

   PROCEDURE REVSIMPLEX (P:FASE;VAR A:MATRIZ;VAR B:COLUNA;VAR C:LINHA);
      VAR N : BYTE;
      ILIMITADA : BOOLEAN;
      V : COLUNA;
      CORDDASH: LINHA;
      CSDASH : REAL;
      CH : CHAR;

      PROCEDURE PRINTDETAILS;
         VAR I,J : BYTE;
             FINISHED : BOOLEAN;
         BEGIN
         FINISHED := (P=FASEII) AND SOLUCAO;
         IF TABLEAU THEN
            BEGIN
            WRITE('   Var. B sica ' , ' ':FWT-5, '  Valor',
                  ' ':BESQ, 'Inversa da Base');
            IF NOT FINISHED THEN
               WRITE(' ':BDIR, ' ':FWT-5, 'A''[I]');
            WRITELN;
            FOR I:=1 TO M  DO
               BEGIN
               WRITE(' ':10-FWI, 'X', BASICA[I]:FWI, ' ':7, BDASH[I]:FWT:DEC);
               FOR J:=1 TO M DO
                  WRITE(BETA[I,J]:FWT:DEC);
               IF NOT FINISHED THEN
                  WRITE(V[I]:FWT:DEC);
               WRITELN;
               END;
            WRITE('    OBJ SIM MULT  ', Z0:FWT:DEC);
            FOR J:=1 TO M DO
               WRITE(PI[J]:FWT:DEC);
            IF P=FASEI THEN
               WRITELN(CSDASH:FWT:DEC)
               ELSE
               IF NOT FINISHED THEN
                  WRITELN(CORDDASH[S]:FWT:DEC)
                  ELSE
                  WRITELN;
            IF P=FASEI THEN
               BEGIN
               WRITE('    ART SIM MULT  ', W0:FWT:DEC);
               FOR J:=1 TO M DO
                  WRITE(SIGMA[J]:FWT:DEC);
               WRITELN(CORDDASH[S]:FWT:DEC)
               END;
            IF PARADA THEN
               TECLA:=READKEY;
            END
         END;

      PROCEDURE NEXTBASICAVARIABLE2(VAR R,S:BYTE;X,C:LINHA;Y:COLUNA);
         VAR  I,J,K : BYTE;
              MIN: REAL;
              SUM,QUOTIENT,DIFF : REAL;
              TIEBROKEN : BOOLEAN;
         BEGIN
         MIN:=MAIORVALOR;
         FOR J:=1 TO N DO
            BEGIN
            SUM := 0.0;
            FOR I:=1 TO M DO
               SUM := SUM + Y[I]*A[I,J];
            CORDDASH[J] := X[J] + SUM;
            IF NAOBASICA[J] THEN
               IF CORDDASH[J]<MIN THEN
                  BEGIN
                  MIN:=CORDDASH[J];
                  S:=J
                  END;
            END;
         IF P=FASEI THEN
            BEGIN
            SUM:=0.0;
            FOR I:=1 TO M DO
               SUM := SUM + PI[I]*A[I,S];
            CSDASH := SUM + C[S]
            END;
         SOLUCAO := CORDDASH[S] > -MENORVALOR;
         IF NOT (SOLUCAO AND (P=FASEI)) THEN
            BEGIN
            IF P=FASEI THEN
               CH:='D'
               ELSE
               CH:='C';
            WRITELN;
            WRITELN('    Itera‡„o ',IT:2);
            IF TABLEAU THEN
               BEGIN
               WRITE('   ');
               FOR J:=1 TO N DO
                  WRITE(' ':FWT-FWI-1, CH, J:FWI);
               WRITELN;
               WRITE('   ');
               FOR J:=1 TO N DO
                  WRITE(CORDDASH[J]:FWT:DEC);
               WRITELN
               END;
            END;
         IF NOT SOLUCAO THEN
            BEGIN
            IF TABLEAU THEN
               BEGIN
               WRITELN;
               WRITELN('    X', S:FWI, ' Entra na Base');
               WRITELN
               END;
            FOR I:=1 TO M DO
               BEGIN
               SUM:=0.0;
               FOR J:=1 TO M DO
                   SUM := SUM + BETA[I,J]*A[J,S];
               V[I]:=SUM
               END;
            END;
         ILIMITADA:=TRUE;
         I:=1;
         WHILE ILIMITADA AND (I<=M) DO
            BEGIN
            ILIMITADA := V[I] < MENORVALOR;
            I:=I+1
            END;
         IF NOT ILIMITADA THEN
            BEGIN
            MIN:=MAIORVALOR;
            FOR I:=1 TO M DO
               IF V[I] > MENORVALOR THEN
                  BEGIN
                  K:=0;
                  REPEAT
                     IF K=0 THEN
                        QUOTIENT := BDASH[I]/V[I]
                        ELSE
                        QUOTIENT := BETA[I,K]/V[I];
                     DIFF := QUOTIENT - MIN;
                     IF DIFF < -MENORVALOR THEN
                        BEGIN
                        MIN:=BDASH[I]/V[I];
                        R:=I;
                        TIEBROKEN:=TRUE
                        END
                        ELSE
                        IF ABS(DIFF) < MENORVALOR THEN
                           BEGIN
                           K:=K+1;
                           MIN:= BETA[R,K]/V[R];
                           TIEBROKEN:=FALSE
                           END
                           ELSE
                           TIEBROKEN:=TRUE
                     UNTIL TIEBROKEN
                  END;
            IF TABLEAU THEN
               PRINTDETAILS;
            IF NOT SOLUCAO THEN
               BEGIN
               WRITELN;
               WRITELN(' X',BASICA[R]:FWI,' da restri‡„o ',R:FWI,' Deixa a base');
               WRITELN
               END;
            NAOBASICA[BASICA[R]]:=TRUE;
            NAOBASICA[S]:=FALSE;
            BASICA[R]:=S
            END;
         END;

      PROCEDURE TRANSFORMVALUES (R,S:BYTE; VAR Y:COLUNA; VAR Y0:REAL);
         VAR I,J : BYTE;
             PIVOT : REAL;
         BEGIN
         PIVOT:=V[R];
         BDASH[R] := BDASH[R]/PIVOT;
         FOR J:=1 TO M DO
            BETA[R,J] := BETA[R,J]/PIVOT;
         FOR I:=1 TO M DO
            BEGIN
            IF I<>R THEN
               BEGIN
               BDASH[I] := BDASH[I] - V[I]*BDASH[R];
               FOR J:=1 TO M DO
                  BETA[I,J] := BETA[I,J] - V[I]*BETA[R,J]
               END;
            Y[I] := Y[I] - CORDDASH[S]*BETA[R,I]
            END;
         Y0 := Y0 - CORDDASH[S]*BDASH[R];
         IF P=FASEI THEN
            BEGIN
            FOR I:=1 TO M DO PI[I] := PI[I] - CSDASH*BETA[R,I];
            Z0 := Z0 - CSDASH*BDASH[R]
            END
         END;

      BEGIN
      SOLUCAO:=FALSE;
      ILIMITADA:=FALSE;
      IF P=FASEI THEN
         N:=N1
         ELSE
         N:=N2;
      REPEAT
         CASE P OF
            FASEI  :
               BEGIN
               NEXTBASICAVARIABLE2(R,S,D,C,SIGMA);
               IF NOT (SOLUCAO OR ILIMITADA) THEN
                  BEGIN
                  TRANSFORMVALUES(R,S,SIGMA,W0);
                  IT:=IT+1
                  END
               END;
            FASEII :
               BEGIN
               NEXTBASICAVARIABLE2(R,S,C,C,PI);
               IF NOT (SOLUCAO OR ILIMITADA) THEN
                  BEGIN
                  TRANSFORMVALUES(R,S,PI,Z0);
                  IT:=IT+1
                  END
               END
            END
         UNTIL SOLUCAO OR ILIMITADA;
      IF ILIMITADA THEN
         WRITELN('    Ilimitada')
      END;

   BEGIN
   INITIALISE(A,B,C);
   FOR I:=1 TO M DO
      FOR J:=1 TO M DO
         BETA[I,J]:=0.0;
   FOR J:=1 TO M DO
      PI[J]:=0.0;
   COMPLETETABLEAU(A,B,C);
   WRITELN('    M�TODO SIMPLEX REVISADO');
   WRITELN;
   SETVALUES(A,B,C);
   IF GCPLUSEC=0 THEN
      BEGIN
      WRITELN('    N„o necessita de fase 1');
      OUTPUTTABLEAU(FASEII,A,B,C);
      WRITELN
      END
      ELSE
      BEGIN
      WRITELN('    FASE 1');
      OUTPUTTABLEAU(FASEI,A,B,C);
      REVSIMPLEX(FASEI,A,B,C);
      WRITELN;
      IF (ABS(W0)>MENORVALOR) OR (NOT SOLUCAO) THEN
         BEGIN
         OK:=FALSE;
         WRITELN('    Fase 1 n„o completada');
         WRITELN('   Soma das vari veis artificiais : ', W0:FWT:DEC)
         END
         ELSE
         BEGIN
         WRITELN('    Fase 1 bem sucedida');
         WRITELN;
         WRITELN('    FASE 2');
         END
      END;
   IF OK THEN
      BEGIN
      REVSIMPLEX(FASEII,A,B,C);
      WRITELN;
      IF NOT SOLUCAO
         THEN WRITELN('    Fase 2 n„o completada')
         ELSE
         BEGIN
         WRITELN;
         WRITELN('   Solu‡„o Final');
         WRITELN;
         WRITELN('    M¡nimo de Z = ', -Z0:FWT:DEC);
         WRITELN;
         WRITE('    Restri‡„o    Base      Valor');
         WRITELN('     Estado       Folga          PI');
         FOR I:=1 TO M DO
            FOLGA[BASICA[I]] := BDASH[I];
         FOR I:=1 TO M DO
            BEGIN
            WRITE(I:9,' ':9,'X',BASICA[I], ' ':12-FWT, BDASH[I]:FWT:DEC, ' ':5);
            IF (I<=GC) OR (I>GCPLUSEC) THEN
               IF NAOBASICA[NUMVAR+I] THEN
                  WRITE('Excesso', 0.0:10:DEC)
                  ELSE  WRITE('Folga', ' ':12-FWT, FOLGA[NUMVAR+I]:FWT:DEC)
               ELSE
               WRITE('Nenhuma   equa‡„o');
            WRITELN(' ':12-FWT, PI[I]:FWT:DEC)
            END
         END
      END;
   WRITELN
   END;

PROCEDURE GOMORY(A : MATRIZ;B : COLUNA;C : LINHA);
   VAR SAVEM,SAVENVAR : BYTE;
   BEGIN
   SAVEM:=M;
   SAVENVAR:=NUMVAR;
   INITIALISE(A,B,C);
   COMPLETETABLEAU(A,B,C);
   WRITELN('    M�TODO DE GOMORY');
   WRITELN;
   IF GCPLUSEC=0 THEN
      WRITELN('   N„o ‚ necess ria Fase 1')
      ELSE
      BEGIN
      WRITELN('     FASE 1');
      SIMPLEXMOD(FASEI,A,B,C);
      WRITELN;
      IF (ABS(W0)>MENORVALOR) OR (NOT SOLUCAO) THEN
         BEGIN
         OK:=FALSE;
         WRITELN('    Fase 1 n„o completada');
         WRITELN('    Soma das vari veis artificiais : ',W0:FWT,DEC)
         END
         ELSE
         BEGIN
         WRITELN;
         WRITELN('    Fase 1 bem sucedida');
         WRITELN;
         WRITELN('    Tableau reduzido para Fase 2')
         END
      END;
   IF OK THEN
      BEGIN
      SIMPLEXMOD(FASEII,A,B,C);
      WRITELN;
      IF NOT SOLUCAO THEN
         WRITELN('     Fase 2 n„o completada')
         ELSE
         BEGIN
         WHILE NOT INTEGERSOLUCAO(A,B,C) OR NOT SOLUCAO DO
            BEGIN
            WRITELN;
            WRITELN('Gerando nova restri‡„o para obter solu‡„o inteira.');
            WRITELN;
            SIMPLEXMOD(FASEII,A,B,C)
            END;
         WRITELN;
         WRITELN('    Solu‡„o Final');
         WRITELN;
         WRITELN('    M¡nimo de Z = ',-Z0:FWT:DEC);
         WRITELN;
         WRITELN('    Restri‡”es    Base      Valor     Estado      Folga');
         FOR I:=1 TO M DO
            FOLGA[BASICA[I]] := B[I];
         FOR I:=1 TO M DO
            BEGIN
            WRITE(I:10,' ':9,'X',BASICA[I], ' ':12-FWT, B[I]:FWT:DEC, ' ':5);
            IF (I<=GC) OR (I>GCPLUSEC) THEN
               IF NAOBASICA[NUMVAR+I] THEN
                  WRITELN('Excesso',0.0:10:DEC)
                  ELSE
                  WRITELN('Folga',' ':12-FWT, FOLGA[NUMVAR+I]:FWT:DEC)
                  ELSE
                  WRITELN('Nenhuma   equa‡„o')
            END
         END
      END;
   M:=SAVEM;
   NUMVAR:=SAVENVAR;
   WRITELN
   END;

PROCEDURE DUALSIMPLEX(A : MATRIZ;B : COLUNA;C : LINHA);
   BEGIN
   INITIALISE(A,B,C);
   COMPLETETABLEAU(A,B,C);
   WRITELN('    M�TODO SIMPLEX / DUAL SIMPLEX');
   WRITELN;
   REPEAT
      OUTPUTTABLEAU(FASEI,A,B,C);
      NEXTBASICAVARIABLE1(NUMVAR,R,S,A,B,C);
      IF NOT (SOLUCAO OR ILIMITADA OR IMPOSSIVEL) THEN
         TRANSFORMTABLEAU(R,S,N1,FASEII,A,B,C);
      UNTIL SOLUCAO OR ILIMITADA OR IMPOSSIVEL;
   WRITELN;
   IF ILIMITADA THEN
      WRITELN('    Vari vel X',S:FWI,' ‚ ilimitada')
      ELSE
      IF IMPOSSIVEL THEN
         WRITELN('   Nenhuma solu‡„o poss¡vel')
         ELSE
         WRITELN('  M¡nimo de Z = ',-Z0:FWT:DEC);
   WRITELN
   END;

PROCEDURE PREPARA;
   BEGIN
   TEXTCOLOR(15);
   TEXTBACKGROUND(3);
   JANELA(7,38,20,35,22,75,2,6);
   GOTOXY(37,21);
   WRITE('Deseja sa¡da na IMPRESS (S/N) ? ');
   IMPRESS:=UPCASE(READKEY)='S';
   TEXTATTR:=CINIC;
   FJANELA(7,38,20,35,22,75,2,6);
   IF IMPRESS THEN
      BEGIN
      CLOSE(OUTPUT);
      ASSIGN(OUTPUT,'PRN');
      REWRITE(OUTPUT);
      WRITELN(CHR(27)+'c'+CHR(2)+CHR(27)+'6');
      WRITELN('M‚todos de Programa‡„o Linear - Autor : Glauber Cintra');
      WRITELN
      END
      ELSE
      BEGIN
      TEXTCOLOR(7);
      TEXTBACKGROUND(0);
      JANELA(24,80,1,1,24,80,1,6);
      CLRSCR
      END;
   END;

PROCEDURE APAGA(LINHA:BYTE);
   BEGIN
   GOTOXY(1,LINHA);
   CLREOL;
   END;

PROCEDURE MENSAGEM(MENS:STRING);

   VAR ESPERA : CHAR;
   BEGIN
   APAGA(25);
   GOTOXY(1,25);
   WRITE(MENS+' Aperte qualquer tecla...');
   ESPERA:=READKEY;
   APAGA(25)
   END;

{ Programa Principal }

BEGIN
POSX:=WHEREX;
POSY:=WHEREY;
SALVA_TELA(TELAORIGINAL);
CORIG:=TEXTATTR;
CLRSCR;
TEXTCOLOR(6);
TEXTBACKGROUND(1);
JANELA(25,80,1,1,24,80,3,6);
GOTOXY(26,2);
WRITELN('M�TODOS DE PROGRAMA€ŽO LINEAR');
GOTOXY(23,3);
WRITELN('Autor : Glauber Cintra - 12Dez1990');
CINIC:=TEXTATTR;
TEXTCOLOR(15);
TEXTBACKGROUND(2);
JANELA(25,1,5,25,19,55,1,6);
GOTOXY(32,7);
WRITE('Op‡„o :');
GOTOXY(27,9);
WRITE('E - Entrar PPL');
GOTOXY(27,10);
WRITE('M - Mostrar PPL');
GOTOXY(27,11);
WRITE('P - Simplex Primeira Fase');
GOTOXY(27,12);
WRITE('F - Full Simplex');
GOTOXY(27,13);
WRITE('R - Simplex Revisado');
GOTOXY(27,14);
WRITE('D - Dual Simplex');
GOTOXY(27,15);
WRITE('G - Algoritmo de Gomory');
GOTOXY(27,16);
WRITE('T - Tableau');
GOTOXY(27,17);
WRITE('S - Sa¡da');
SALVA_TELA(TELA);
OPCAO:=' ';
PPL:=FALSE;
IMPRESS:=FALSE;
TABLEAU:=TRUE;
PARADA:=FALSE;
M:=0;
WHILE OPCAO<>'S' DO
   BEGIN
   GOTOXY(39,16);
   IF TABLEAU THEN
      IF PARADA THEN
         WRITE('(ON/ON)  ')
         ELSE
         WRITE('(ON/OFF) ')
      ELSE
      WRITE('(OFF/OFF)');
   GOTOXY(40,7);
   OPCAO:=UPCASE(READKEY);
   WRITE(OPCAO);
   CASE OPCAO OF
      'E' :
         BEGIN
         TEXTCOLOR(7);
         TEXTBACKGROUND(0);
         CLRSCR;
         INPUTDATA(A,B,C,M,NUMVAR)
         END;
      'M' :
         IF PPL THEN
            BEGIN
            PREPARA;
            PRIMEIRO:=TRUE;
            WRITE('MIN Q(X) =');
            FOR I:=1 TO NUMVAR DO
               IF C[I]<>0 THEN
                  IF PRIMEIRO OR (C[I]<0) THEN
                     BEGIN
                     PRIMEIRO:=FALSE;
                     WRITE(C[I]:FWT:DEC,'X',I)
                     END
                     ELSE
                     WRITE(' +',C[I]:FWT:DEC,'X',I);
            WRITELN;
            WRITELN('SUJEITO A :');
            FOR J:= 1 TO M DO
               BEGIN
               PRIMEIRO:=TRUE;
               FOR I:= 1 TO NUMVAR DO
                  IF A[J,I]<>0 THEN
                     IF PRIMEIRO OR (A[J,I]<0) THEN
                        BEGIN
                        PRIMEIRO:=FALSE;
                        WRITE(A[J,I]:FWT:DEC,'X',I)
                        END
                        ELSE
                        WRITE(' +',A[J,I]:FWT:DEC,'X',I);
               WRITELN(SINAL[J],B[J]:FWT:DEC)
               END;
            IF NOT IMPRESS THEN
               MENSAGEM('')
            END
            ELSE
            MENSAGEM('Primeiramente entre PPL.');
      'P' :
         IF PPL THEN
            IF PRIMAL THEN
               BEGIN
               PREPARA;
               PRIMALSIMPLEX(A,B,C);
               IF NOT IMPRESS THEN
                  MENSAGEM('')
               END
               ELSE
               MENSAGEM('Este PPL n„o pode ser resolvido por este m‚todo.')
            ELSE
            MENSAGEM('Primeiramente entre PPL.');
      'F' :
         IF PPL THEN
            BEGIN
            PREPARA;
            FULLSIMPLEX(A,B,C);
            IF NOT IMPRESS THEN
               MENSAGEM('')
            END
            ELSE
            MENSAGEM('Primeiramente entre PPL.');
      'R' :
         IF PPL THEN
            BEGIN
            PREPARA;
            SIMPLEXREVISADO(A,B,C);
            IF NOT IMPRESS THEN
               MENSAGEM('')
            END
            ELSE
            MENSAGEM('Primeiramente entre PPL.');
      'D' :
         IF PPL THEN
            IF PRIMAL THEN
               BEGIN
               PREPARA;
               DUALSIMPLEX(A,B,C);
               IF NOT IMPRESS THEN
                  MENSAGEM('')
               END
               ELSE
               MENSAGEM('Este PPL n„o pode ser resolvido por este m‚todo.')
            ELSE
            MENSAGEM('Primeiramente entre PPL.');
      'I' :
         IF PPL THEN
            BEGIN
            PREPARA;
            GOMORY(A,B,C);
            IF NOT IMPRESS THEN
               MENSAGEM('')
            END
            ELSE
            MENSAGEM('Primeiramente entre PPL.');
      'T' :
         IF NUMVAR<10 THEN
            BEGIN
            TEXTCOLOR(13);
            TEXTBACKGROUND(4);
            JANELA(7,40,20,14,23,55,4,5);
            GOTOXY(16,21);
            WRITE('Deseja ver Tableaus (S/N) :');
            GOTOXY(16,22);
            WRITE('Deseja parada entre Tableaus (S/N) :');
            GOTOXY(44,21);
            TABLEAU:=UPCASE(READKEY)='S';
            IF TABLEAU THEN
               BEGIN
               WRITE('S');
               GOTOXY(53,22);
               PARADA:=UPCASE(READKEY)='S'
               END;
            TEXTATTR:=CINIC;
            FJANELA(7,40,20,14,23,55,4,5)
            END
            ELSE
            MENSAGEM('N„o ‚ poss¡vel mostrar Tableau, mais de 9 vari veis.');
      END;
   IF IMPRESS THEN
      BEGIN
      CLOSE(OUTPUT);
      IMPRESS:=FALSE;
      ASSIGNCRT(OUTPUT);
      REWRITE(OUTPUT)
      END;
   RESTAURA_TELA(TELA);
   TEXTCOLOR(6);
   TEXTBACKGROUND(2)
   END;
TEXTATTR:=CINIC;
FJANELA(25,1,5,25,19,55,1,6);
TEXTATTR:=CORIG;
FJANELA(25,80,1,1,24,80,3,6);
RESTAURA_TELA(TELAORIGINAL);
GOTOXY(POSX,POSY)
END.