Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Симплекс-метод, Минимизация целевой функции... 
:(
    Опции темы
Maverick
  Дата 24.3.2004, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: нет
Всего: 10



Здравствуйте....

Заранее говорю, что по форуму порылся и некоторые ссылки в начале раздела посмотрел.... На форуме, кроме общих рассуждений ничего нет...

Мне необходим алгоритм минимизации целевой функции с ограничивающими неравенствами (классика линейного программирования)... Ребята, хотя бы блок-схему этого чертового решения... Лучше симплекс-метод, у меня есть пара программ без исходников... Вроде работает... Сразу говорю - вручную я его никогда не использовал... Меня очень сроки поджимают, поэтому вот так выхожу в эфир....

Если кто может поделиться кодами в Дельфях - буду благодарен... или сайтик какой с исходниками... Я разберусь....


--------------------
smile
PM ICQ GTalk   Вверх
Maverick
Дата 24.3.2004, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: нет
Всего: 10



 Вот порылся поплотнее и кое-что нашел...
Кто понимает - скажите, это оно?

=====================================================
Пpивожy кpаткое описание симплекс  метода. 

Регyляpный симплекс - множество  (n+1) pавноyдаленных точек в  n-меpном 
пpостpанстве (напpимеp тpеyгольник  в двyмеpном пpостpанстве). 

Пyсть F(X) - фyнкция  оптимизации, X=(x1, x2, ...,  xn). 

1) Hаходим значения фyнкции  оптимизации на веpшинах симплекса 
   f1=F(X1), f2=F(X2),  ...,fn+1=F(Xn+1); 

2) Сpеди всех f1,...,fn+1  находим наибольшее значение fh,  следyющее за ним 
значение fg, наименьшее значение  fl и соответствyющие им точки  Xh, Xg и Xl. 

3) Опpеделяем цент тяжести  всех точек, за исключением  точки наибольшего 
   значения Xh и  значение в этой точке f0=F(X0) 
      X0=(X1+X2+...+Xn)/n,  Xi<>Xh; 

4) Hаходим точкy Xr отpажением  точки Xh относительно центpа  тяжести X0 по 
фоpмyле 
      Xr=(1+alpha)*X0  - alpha*Xh, alpha>0; 
      fr=F(Xr); 

5) Сpавниваем полyченное значение  fr с имеющимся минимальным  fl 

   5.1) Если fr< fl, следовательно данное напpавлением  из точки X0 в точкy  Xr 
обеспечивает полyчение наименьшего  значения фyнкции. Поэтомy мы 
пpоизводим pастяжение в этом  напpавлении и полyчаем точкy  Xe 
     Xe=(1-gamma)*X0  + gamma*Xr, gamma>1, 
     fe=F(Xe); 

5.1.1) Если fe<fl, то  заменяем точкy Xh на Xe  и пеpеходим к 8) 
5.1.2) Если fe>=fl, следовательно  yлyчшение не достигнyто, т.к.  мы 
        пеpеместились слишком далеко от  X0 к Xr, поэтомy отбpасываем 
        точкy Xe. Заменяем точкy  Xh на Xr и пеpеходим  к 8) 

   5.2) Если fr> fl, но fr<=fg, то Xr  является лyчшей точкой по  отношению к 
Xh и Xg, заменяем Xh  на Xr и пеpеходим к  8) 

   5.3) Если fr> fl и fr>fg, пеpеходим  к шагy сжатия 6) 

6) Если fr<fh, то  заменяем Xh на Xr и  fh на fr. 
   Таким обpазом  мы пеpеместились слишком далеко  от Xh к X0. Для испpавления 
этого опpеделяем точкy Xc 

        Xc=(1-betta)*X0 + betta*Xr, betta< 1. 
        fc=F(Xc). 

7) Сpавниваем значения фyнкций  fc и fh. 
   Если fc<fh,  то заменяем Xh на Xc  и fh на fc. 

8) Уменьшаем pазмеpность симплекса  делением пополам pасстояния от  каждой точки 
   Xi до точки  наименьшего значения Xl 

        Xi=Xi + 0.5*(Xi-Xl), i=1,..,n+1; 
        fi=F(Xi). 

9) Пpовеpка сходимости. 
   Если сpеднеквадpатическое  отклонение s 
 n+1    n+1 
 __   _     __ 
 \  (fi - f)^2         -    \   fi 
        s=/  --------  ,     где f = /   ----- , 
 --    n+1     --  n+1 
 i    i 

   меньше напеpед  заданной величины Eps (s  < Eps), то все значения  фyнкции 
   на yзлах симплекса  очень близки дpyг к дpyгy  и лежат вблизи точки минимyма 
   Xl и итеpации  можно считать законченными. 
   Ели же s  > Eps, то пеpеходим к  пyнктy 3). 

     Sincerely  Yours.  № Alex. _ 

Код

 { Модифицированный симплексный  метод Спендли-Хекста-Химсворта } 
 { Косенков А.М.       2:5030/444.4@FidoNet         } 
 Program SimplexMethod; 
 Uses Crt; 

 Type 
      TFloat  = Extended; 
 Const 
      N_S  = 3; { Максимальное число  переменных } 
      Max_Float  = 1.0e4932; 
 Type 
      Vector  = Array[1..Succ(N_S)] Of TFloat; 
      Matrix  = Array[1..Succ(N_S), 1..N_S]  Of TFloat; 
      OptimFunc  = Function(N: Byte; X: Vector):  TFloat; 
 Var 
      X        : Vector; 
      H,  Fmin : TFloat; 
      It       : Integer; 
 { Функция оптимизации  } 
 Function OFunc(N: Byte;  X: Vector): TFloat; FAR; 
 Begin 
    OFunc:=100*Sqr(X[2]  - 1) + Sqr(X[1] + 2); 
 End; 

 {**************************** *****************************************} 
 {*   Процедура Simplex.        *} 
 {*    Оптимизация  функции многих переменных методом  Hелдера-Мида     *} 
 {*  (модифицированный  симплексный метод Спендли-Хекста-Химсворта).    *} 
 {*        *} 
 {*  Входные  параметры  :       *} 
 {*   N - Число  переменных;         *} 
 {* Eps - Точность определения  минимума;        *} 
 {*   X - Hа  входе процедуры содержит начальное  прибли-   *} 
 {*        жение к экстремуму;        *} 
 {*   H - Шаг;        *} 
 {*  IT - Допустимое  число итераций;        *} 
 {*        OFunc - Внешняя процедура  оптимизируемой функции.        *} 
 {*        *} 
 {*  Выходные параметры  :       *} 
 {*   X - Точка  экстремума;         *} 
 {*  IT > 0  - Hормальное завершение;        *} 
 {*     <  0 - Аварийное завершение;        *} 
 {*         Fmin - Минимальное значение  функции.        *} 
 {**************************** *****************************************} 
 Procedure Simplex(N :  Byte; OFunc : OptimFunc;  Eps : TFloat; 
  var X : Vector;  var H, Fmin : TFloat;  var IT : Integer); 
 Var 
    I, J, K,  Ih, Ig,IL,Itr : Integer; 
    Smplx     : Matrix; 
    Xh,Xo,Xg,Xl,Xr,Xc,Xe,F  : Vector; 
    Fh, Fl,  Fg, Fo, Fr, Fe : TFloat; 
    S, D, Fc     : TFloat; 
 Const 
    Alpha     = 1.1; { Коэф.  отражения  } 
    Betta     = 0.5; { Коэф.  сжатия     } 
    Gamma     = 2.0; { Коэф.  растяжения } 
 Begin 
     { Hачальное  приближение X[i] } 
    For i:=1  To N Do Smplx[1,i]:=X[i]; 
     { Построение  симплекса на начальном приближении  X[i] } 
    For i:=2  To Succ(N) Do 
        For j:=1 To N Do 
  If j = pred(i)  Then Smplx[i,j]:=Smplx[1,j] +  H 
  Else Smplx[i,j]:=Smplx[1,j]; 
     { Значение  функции F[i] на вершинах  симплекса } 
    For i:=1  To Succ(N) Do 
    Begin 
        For j:=1 To N Do X[j]:=Smplx[i,j]; 
        F[i]:=OFunc(N, X); 
    End; 
    Itr:=0; Eps:=Abs(Eps);  IT:=Abs(IT); 
     { Цикл  итераций } 
    REPEAT 
{ Max и Min на  вершинах } 
        Fh:=-Max_Float; Fl:=Max_Float; 
        For i:=1 To Succ(N) Do 
        Begin 
  If F[i]>Fh Then  Begin Fh:=F[i]; Ih:=i End; 
  If F[i]<Fl Then  Begin Fl:=F[i]; IL:=i End; 
        End; 

        Fg:=-Max_Float; 
        For i:=1 To Succ(N) Do 
 If (F[i]>Fg)and(i<>Ih)  Then Begin Fg:=F[i]; Ig:=i  End; 
{ Дополнительные точки симплекса  } 
        For j:=1 To N Do 
        Begin 
  Xo[j]:=0; { Центр  тяжести } 
  For i:=1 To Succ(N)  Do If i<>Ih Then Xo[j]:=Xo[j]+Smplx[i,j]; 
  Xo[j]:=Xo[j]/N;  {  Среднее арифмет. } 
  Xh[j]:=Smplx[Ih,j]; 
  Xl[j]:=Smplx[IL,j]; 
  Xg[j]:=Smplx[Ig,j]; 
        End; 
        Fo:=OFunc(N, Xo); { Значение  в центре тяжести } 

{ ОТРАЖЕHИЕ с коэф.  Alpha} 
        For j:=1 To N Do Xr[j]:=Xo[j]  + Alpha*(Xo[j]-Xh[j]); 
        Fr:=OFunc(N, Xr); { Значение  в точке Xr } 

        If Fr<Fl Then 
        Begin 
   { РАСТЯЖЕHИЕ  с коэф. Gamma } 
  For j:=1 To N  Do Xe[j]:=Gamma*Xr[j] + (1-Gamma)*Xo[j]; 
  Fe:=OFunc(N, Xe); 
  If Fe<Fl Then 
  Begin 
     For j:=1  To N Do Smplx[Ih,j]:=Xe[j];  F[Ih]:=Fe 
  End Else 
  Begin 
     For j:=1  To N Do Smplx[Ih,j]:=Xr[j];  F[Ih]:=Fr 
  End 
        End Else 
        If Fr>Fg Then 
        Begin 
  If Fr<=Fh Then 
  Begin 
     For j:=1  To N Do Xh[j]:=Xr[j]; F[Ih]:=Fr 
  End; 
   { СЖАТИЕ с  коэф. Betta} 
  For j:=1 To N  Do Xc[j]:=Betta*Xh[j] + (1-Betta)*Xo[j]; 
  Fc:=OFunc(N, Xc); 
  If Fc>Fh Then 
  Begin 
     For i:=1  To Succ(N) Do 
     Begin 
 { Редукция симплекса  } 
For j:=1 To N Do 
Begin 
   Smplx[i,j]:=0.5*(Smplx[i,j]  + Xl[j]); 
   X[j]:=Smplx[i,j] 
End; 
F[i]:=OFunc(N, X); 
     End 
  End Else 
  Begin 
     For j:=1  To N Do Smplx[Ih,j]:=Xc[j];  F[Ih]:=Fc 
  End 
        End Else 
        Begin 
  For j:=1 To N  Do Smplx[Ih,j]:=Xr[j]; F[Ih]:=Fr 
        End; 

        { Оценка стандартного отклонения  (с.к. значения) } 
        S:=0; D:=0; 
        For i:=1 To Succ(N) Do  Begin S:=S + F[i]; D:=D  + Sqr(F[i]) End; 
        S:=Sqrt(Abs((D - Sqr(S)/Succ(N))/Succ(N))); 
        Inc(Itr); 
    UNTIL (S< =Eps) or (Itr>IT); 

    If Itr>IT  Then IT:=-Itr Else IT:=Itr; 
    X:=XL;   { Вектор решения } 
    Fmin:=F[IL];  { Минимальное значение функции  } 
 End; 

 BEGIN 
    ClrScr; 
      X[1]:=1.5;  X[2]:=0.2; { Hачальное пpиближение  } 
      H:=0.5;  It:=80; 
      Simplex(2,  OFunc, 1.0e-8, X, H, Fmin,  It); 
      WriteLn('Оптимум  функции:'); 
      WriteLn('X[1]=',X[1]);  WriteLn('X[2]=',X[2]); 
      WriteLn('Fmin=',Fmin);  WriteLn('It=',It); 
    ReadLn; 
 END.
=====================================================

Взято отсюда....отсюда 

Это сообщение отредактировал(а) maxim1000 - 26.12.2007, 11:41


--------------------
smile
PM ICQ GTalk   Вверх
Mal Hack
Дата 24.3.2004, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: 1
Всего: 261



Maverick, какой конеретно метод тебе нужен ???
Есть симплекс, есть двухэтапный, есть двойственный, есть метод Гомори...
То что ты написал я никак не могу присобачить к обычному симплексу.
В обычном симплексе (по крайней мере как мы в технаре на КМ решали) все проще.
Есть система неравенств (из 2 переменных и 2 уравнения с х1 и х2) и целевая функция.
Далее приводим эту систему неравенств к системе уравнений, т.е. прибавляем в первое уравнение х3 (если знак больше - вычитаем). Аналогично для второого (х4).
Затем смотрим количество базисных (те что добавляли) и свободных (те что были - х1 и х2).
Потом выражаем из любого уравнения свободную переменную, которая возрастает, подставляем в другое уравнение, а затем подставляем в целевую функцию.
После этого строим таблицу (матрицу).
В качестве строк - свободные переменные, в качестве столбцов - базисные.
Заполняем так матрицу таким образом, что например строка x1 будет содержать значения 4 -1 2, со столбцами - B (обязательно) х3 х2. Из уравнение: х1 = - (-х3 + 2*х2).
Плюс строчка елевой функции.
Затем быбираем ячейку, находя его не пересечениит, где максимальный элемент в строке целевой функции (исключая столбец B), и минимальное отношение в элемента строки из столбца B к элементу строки столбца, где выбран максимум.
Потом решаем таблицу.
Эту ячейку заменяем 1/саму себя, чтроку - делим значение на этот элемент, стоблбец - тодже но с протиивоположным знаком. Остальные - значение ячейки минус произведение элемента в ключевой строке на элемент ключевого столбца и на 1/значение ключевой ячейки.
В итоге должно получиться что в последней строке все числа - отрицательные.
PM ICQ   Вверх
Maverick
Дата 25.3.2004, 09:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: нет
Всего: 10



Ну это оно самое.... Только у меня целевая функция с n неизвестными....

Z=X11*K11+X12*K12+....+XNM*KNM -> MIN

и куча неравенств типа X11*K11+X12*K12+....+XNM*KNM<=L1
и тд... где учавствуют разные Х в разных комбинациях...

Общий вид только есть... все остальное всегда произвольное....
Теорией я владею.... Я с алгоритмом туплю чего-то....


--------------------
smile
PM ICQ GTalk   Вверх
Maverick
Дата 25.3.2004, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1307
Регистрация: 22.9.2003
Где: Odessa, Ukraine

Репутация: нет
Всего: 10



 Ху-уууу.... Вот нашел... Ужасно древний и не очень стильный вариант, но работает... Доработаю - выложу доработанный...

Код

====================================================
program Project1;

{$APPTYPE CONSOLE}
uses SysUtils;

type ten = array [1..10] of integer;
     TwoD = array [1..11,1..36] of real;
     OneD = array [1..35] of real;

var
    b, c, x: OneD;
    a: TwoD;
    n, m, j: integer;
    print1, print2: boolean;
    opt: real;

{ Simplex algorithm for the linear programming problem with m
constraints and n real or slack variables, where the constraints are all
off the = or <= kind. b[1...m] are the non-negative constants of the
right hand sides. One new variable x[n+1] is added to the i th constraint
(either slack for <= or artificial for =). c[1..n+m] are the cost
coefficients associated with the variables x[1..n+m].}

procedure output(m, ncols: integer; tableau: TwoD; basis: ten;
                    var x: OneD);
var i, j, mp1: integer;
    objf: real;
begin
     mp1 := m + 1;
     for i := 1 to mp1 do begin
         writeln;
         for j := 1 to ncols do write(tableau[i,j]:5:2,'  ')
         end;
     objf := tableau[mp1,ncols];
     writeln;
     writeln('Function = ', objf:5:2);
     writeln;
     for j := 1 to ncols-1 do x[j] := 0.0;
     for i := 1 to m do x[basis[i]] := tableau[i,ncols];
     writeln('Solitions , x[1] to x[',ncols-1,']');
     for j := 1 to ncols-1 do write(x[j]:5:2,'  ');
     writeln;  writeln;
      readln;
             // sleep(2000);
end;

function simplex(n,m: integer; a: TwoD; b, c: OneD; var x: OneD;
                               print1,print2: boolean): real;
var i, j, k, rowsub, iter, ncols, mp1, ncolsm1: integer;
    basis: ten;
    tableau: TwoD;
    zjcj, theta, theta1, delete, pivot, objf: real;

label    bypass, OK, out, exit, return;

begin
    ncols := n + m + 1;
    ncolsm1 := ncols -1;
    mp1 := m + 1;
    if (ncols*mp1 > 396) or (ncols > 36) then begin
       writeln('Problem too big. Quitting...');
       objf := 0.0;
       goto out;
       end;
    {Otherwise, fill in the simplex tableau}
       for i := 1 to mp1 do
           for j := n+1 to ncolsm1 do tableau[i,j] := 0.0;
       tableau[mp1,ncols] := 0.0;
       for i := 1 to m do begin
           tableau[mp1,ncols] := tableau[mp1,ncols] + b[i]*c[n+i];
           for j := 1 to n do tableau[i,j] := a[i,j];
           tableau[i,n+i] := 1.0;  tableau[i,ncols] := b[i];
           basis[i] := i + n
           end;
       for j := 1 to n do begin
           tableau[mp1,j] := -c[j];
           for i := 1 to m do tableau[mp1,j] := tableau[mp1,j]
                                + tableau[i,j]*c[n+i]
           end;
       if print1 then begin
           writeln;
           writeln('The initial table is:');
           output(m, ncols, tableau, basis, x)
           end;
       iter := 0;
return:
       zjcj := tableau[mp1,1];  k := 1;
       for j := 2 to ncolsm1 do
           if tableau[mp1,j] > zjcj then begin
              zjcj := tableau[mp1,j];
              k := j    end;
       if zjcj <= 0.0 then begin
exit:     for j := 1 to ncolsm1 do x[j] := 0.0;
          if print1 then begin
             writeln;
             writeln('The final table is:');
             output(m, ncols, tableau, basis, x);
             end;
          objf := tableau[mp1,ncols];
          goto out;
          end;
       for i := 1 to m do
           if tableau[i,k] > 0 then goto OK;
       writeln;
       writeln('Objective function unbounded. Computation ends.');
       goto exit;
OK:    theta := tableau[i,ncols]/tableau[i,k];
       rowsub := i;
       for j := i+1 to m do if tableau[j,k]>0 then begin
           theta1 := tableau[j,ncols]/tableau[j,k];
           if theta1 < theta then begin
              theta := theta1;  rowsub := j  end;
           end;
       basis[rowsub] := k;
{ Do Gauss-Jordan reduction using tableau[rowsub,k] as pivot}
       pivot := tableau[rowsub,k];
       for j := 1 to ncols do tableau[rowsub,j] := tableau[rowsub,j]/pivot;
       for i := 1 to mp1 do begin
           delete := tableau[i,k];
           if (delete = 0) or (i = rowsub) then goto bypass;
           for j := 1 to ncols do
               tableau[i,j] := tableau[i,j] - delete*tableau[rowsub,j];
bypass:    end;
       iter := iter + 1;
       if print2 then begin
          writeln;
          writeln('Table # ', iter);
          output(m, ncols, tableau, basis, x);
          end;
       goto return;
out:
       simplex := objf
end;

begin
     n := 9;  m := 6;

     a[1,1] := 1;  a[1,2] := 0.33; a[1,3] := 0.33; a[1,4] := 0; a[1,5] := 0;      a[1,6] := 0;    a[1,7] := 0;     a[1,8] := 0;    a[1,9] := 0; b[1] := 3000;
     a[2,1] := 0;  a[2,2] := 0;    a[2,3] := 0;    a[2,4] := 0; a[2,5] := 0.66;   a[2,6] := 0.66; a[2,7] := 0;     a[2,8] := 0;    a[2,9] := 0; b[2] := 3000;
     a[3,1] := 0;  a[3,2] := 0;    a[3,3] := 0;    a[3,4] := 0; a[3,5] := 0;      a[3,6] := 0;    a[3,7] := 0.33;  a[3,8] := 0.66; a[3,9] := 1; b[3] := 3000;

     a[4,1] :=1;   a[4,4] := 0;   a[4,7] := 0;       b[4] := 2000;
     a[5,2] :=0.33;a[5,5] := 0.66;a[5,8] := 1;      b[5] := 3000;
     a[6,3] :=0.33;a[6,6] := 0.66; a[6,9] := 1;      b[6] := 3000;


     c[1] := -1;  c[2] := -0.33;  c[3] := -0.33;  c[4] := 0;
     c[5] := -0.66;  c[6] := -0.66;  c[7] := 0;  c[8] := -1;
                     c[9] := -1;


     print1 := true;  print2 := true;

     opt := simplex(n,m,a,b,c,x,print1,print2);

     for j := 1 to m+n do writeln('x[',j,'] = ',x[j]:5:2);

     writeln;
       writeln('Optimum function value = ', opt:10:2);
         readln;
end.
====================================================


Mal Hack... Спасибо за объяснение... Еще раз книжку перечел. глядя на твое сообщение - вроде полегче стало..... 

Это сообщение отредактировал(а) maxim1000 - 26.12.2007, 11:38


--------------------
smile
PM ICQ GTalk   Вверх
Peace
Дата 16.5.2004, 22:26 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Выложи доработанные исходники, плиз...
  Вверх
achmed
Дата 22.5.2004, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 150
Регистрация: 12.4.2004

Репутация: нет
Всего: нет



>Вот порылся поплотнее и кое-что нашел...
>Кто понимает - скажите, это оно?
>
>=====================================================
>Пpивожy кpаткое описание симплекс метода.

это метод деформируемого многогранника, алгоритм Нелдера и Мида.
Оптимизация произвольной (нелинейной, в отличие от симплекс-метода) фукции,
но без ограничений (сегодня его реализовывал).
PM MAIL   Вверх
Гость_Serzh
Дата 31.10.2005, 12:31 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Есть ли текст программ Симплекса написанная на Дельфи ?
Помогите если можете smile
  Вверх
Guest
Дата 2.11.2005, 12:51 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











 Код писался 5 лет назад.
Все забыто.
Объявлений классов-матриц и векторов нет. Можно заменить на обычные массивы.
Может разберешься.
Пример внизу.

Код

unit ччч;

interface

type
 Float=double;
 PFloat=^Float;
 FloatArray=array[0..1000] of float;
 PFloatArray=^FloatArray;
 IntArray=array[0..1000] of integer;
 PIntArray=^IntArray;

const
 Big_IEEEDouble   = 1.79E+0308;  { max double }
 Small_IEEEDouble = 4.94E-0324;  { min double }
 Tiny_IEEEDouble  = 2.00E-0016;  { min double such that 1+Tiny_IEEEDouble > 1 }
 Big_IEEEExt      = 5.95E+4931;  { max extended }
 Small_IEEEExt    = 3.36E-4932;  { min extended }
 Tiny_IEEEExt     = 2.00E-0019;  { min extended such that 1+Tiny_IEEEextended > 1 }

function Simplex(A:TFloatMatrix; B:TFloatArray; C:TFloatArray; ConCnt,XCnt:integer;
 EBasis:boolean; IBasis:TIntArray; X:TFloatArray; var OValue:extended; var Iter:longint;
 MaxIter:longint; LECnt,GECnt:integer; Bi:TFloatMatrix; var Error:double):integer;

implementation

function Simplex(A:TFloatMatrix; B:TFloatArray; C:TFloatArray; ConCnt,XCnt:integer;
 EBasis:boolean; IBasis:TIntArray; X:TFloatArray; var OValue:extended; var Iter:longint;
 MaxIter:longint; LECnt,GECnt:integer; Bi:TFloatMatrix; var Error:double):integer;
{ Input:
   A[ConCnt,XCnt] - coefficients of the constraints;
   B[ConCnt] - right-hand side of the constraints;
   C[XCnt] - vector of "costs" in the objective function;
   ConCnt - dimention of array B (number of constraints);
   XCnt - 2nd dimention of array A (number of variables);
   EBasis - if false, the routine selects its own initial basis,
            else indices of the initial basis should be in IBasis;
   IBasis[ConCnt] - indices of the variables in the basis;
   MaxIter - max number of iterations;
   LECnt - number of <= constraints;
   GECnt - number of >= constraints;
  Output:
   Result -
    = 0 the problem was solved
    = 1 the solution may have been obtained
    = 2 MaxIter iterations were performed; more needed
    = 3 sufficient accuracy could not be maintained to solve the problem
    = 4 the problem has an unbounded solution
    = 5 the problem has no solution
    = 6 input error detected
   X[] - dimention must be >=XCnt+LECnt+GECnt.
         if Result in [0,1], it contains the values of the original,
         slack and surplus variables;
   OValue - if Result in [0,1], contains the value of the objective;
   Iter - number of iterations used;
   Bi[ConCnt,ConCnt] - the inverse of the basis matrix;
   Error - the estimated relative error achieved.
}
label 22,30,32,100,200,300,360,430,440,450,460,500,580,600,601,610,630,650,660,
 680,700,800;
var eps0,Errmn,Errmx,xmax,rtol,tmp,total,bnorm,binorm,t,dt,dsump,dsumn,s,tol:extended;
 rmin,amax,rerr1,dsum,bmax,ratio,epsi,eps,cons,bmin,cmin,sgn,w:extended;
 icount,mcheck,ms,m,i,j,ns,n,num,bflag,ibeg,iend,kj,l,ierr,iout,imin,lrow:integer;
 ip,jp,nstep,nrow,ll,npos,ii,k:integer;
 Xb,Y:PFloatArray; Basis,Indx:PIntArray;

 procedure proc220;
 var i,j:integer;
 begin
  for i:=0 to n-1 do X[i]:=0;
  for i:=0 to m do begin
   j:=IBasis[i];
   if j<n then X[j]:=Xb^[i]
  end
 end;

 procedure Done;
 begin
  FreeMem(Xb,ConCnt*SizeOf(float));
  FreeMem(Y,ConCnt*SizeOf(float));
  FreeMem(Basis,(ConCnt+Xcnt)*SizeOf(integer));
  FreeMem(Indx,ConCnt*SizeOf(integer));
 end;

 procedure Croutl(Bi:TFloatArray; iend:integer; var ierr:integer);
 label 20,30;
 var i,maxdim,mcol,k,kcol,kk,nk,lk,l,lj,kj,nm1,km1,kp1,kcount,ik:integer;
  kl,jcol,il,ncol,jj,j,nmk,lmin,n,m,ij,nmj:integer;
  c,dsum,pmin,s:extended;
 begin
  n:=ConCnt;
  m:=n-1;
  maxdim:=sqr(n);
  mcol:=iend*n;
  if iend<>0 then begin
   { process the first iend columns of Bi }
   kcol:=0;
   for k:=0 to iend-1 do begin
    kk:=kcol+k;
    nk:=kcol+n-1;
    lk:=kk;
    while lk<=nk do begin
     if Bi[lk]<0 then goto 20;
     if Bi[lk]>0 then goto 30
    end;
    ierr:=1;
    exit;
 20:
    lj:=mcol+lk-kcol;
    while lj<maxdim do begin
     Bi[lj]:=-Bi[lj];
     inc(lj,n)
    end;
 30:
    l:=lk-kcol;
    Indx^[k]:=l;
    if k<>l then begin
     lj:=lk;
     kj:=kk;
     while kj<n do begin
      {c:=Bi[kj]; Bi[kj]:=Bi[lj]; Bi[lj]:=c;}
      Bi.SwapCells(kj,lj);
      inc(lj,n);
      inc(kj,n)
     end
    end;
    inc(kcol,n)
   end;
  end;
  { process the remaining columns of Bi }
  nm1:=n-2;
  ierr:=0;
  pmin:=0;
  ibeg:=iend;
  if ibeg<>n-1 then begin
   k:=ibeg;
   km1:=iend-1;
   kp1:=k+1;
   kcol:=mcol;
   kk:=kcol+k;
   for kcount:=ibeg to nm1 do begin
    { search for the k-th pivot element }
    l:=k;
    s:=abs(Bi[kk]);
    for i:=kp1 to n-1 do begin
     ik:=kcol+i;
     c:=abs(Bi[ik]);
     if s>=c then continue;
     l:=i;
     s:=c
    end;
    if (k>ibeg) and (s>=pmin) then
    else begin
     pmin:=s;
     if s=0 then begin
      ierr:=1;
      exit
     end
    end;
    { interchanging rows k and l }
    Indx^[k]:=l;
    if k<>l then begin
     kj:=mcol+k;
     lj:=mcol+l;
     while kj<maxdim do begin
      {c:=Bi[kj]; Bi[kj]:=Bi[lj]; Bi[lj]:=c;}
      Bi.SwapCells(kj,lj);
      inc(lj,n);
      inc(kj,n)
     end
    end;
    { compute the k-th row of U }
    c:=Bi[kk];
    if k<=ibeg then begin
     kj:=kk+n;
     while kj<maxdim do begin
      Bi[kj]:=Bi[kj]/c;
      inc(kj,n)
     end
    end
    else begin
     kl:=mcol+k;
     for l:=ibeg to km1 do begin
      Y^[l]:=Bi[kl];
      inc(kl,n)
     end;
     kj:=kk+n;
     while kj<maxdim do begin
      jcol:=kj-k;
      dsum:=-Bi[kj];
      for l:=ibeg to km1 do begin
       lj:=jcol+l;
       dsum:=dsum+Y^[l]*Bi[lj]
      end;
      Bi[kj]:=-dsum/c;
      inc(kj,n)
     end;
    end;
    { compute the k-th column of L }
    km1:=k;
    k:=kp1;
    kp1:=k+1;
    inc(kcol,n);
    kk:=kcol+k;
    for l:=ibeg to km1 do begin
     lk:=kcol+l;
     Y^[l]:=Bi[lk]
    end;
    for i:=k to n-1 do begin
     il:=mcol+i;
     dsum:=0;
     for l:=ibeg to km1 do begin
      dsum:=dsum+Bi[il]*Y^[l];
      inc(il,n)
     end;
     Bi[il]:=Bi[il]-dsum
    end
   end;
  end;
  { check the k-th pivot element }
  ncol:=maxdim-n-1;
  c:=abs(Bi[maxdim-1]);
  if c>pmin then
  else
  if c=0 then begin
   ierr:=1; exit
  end;
  { replace L with the inverse of L }
  if ibeg<>n-1 then begin
   jj:=mcol+ibeg;
   i:=n+1;
   for j:=ibeg to nm1 do begin
    Bi[jj]:=1/Bi[jj];
    Y^[j]:=Bi[jj];
    kj:=jj;
    for km1:=j to nm1 do begin
     k:=km1+1;
     inc(kj);
     dsum:=0;
     kl:=kj;
     for l:=j to km1 do begin
      dsum:=dsum+Bi[kl]*Y^[l];
      inc(kl,n)
     end;
     Bi[kj]:=-dsum/Bi[kl];
     Y^[k]:=Bi[kj]
    end;
    inc(jj,i)
   end
  end;
  Bi[maxdim-1]:=1/Bi[maxdim-1];
  if n=1 then exit;
  { solve UX=Y where Y is the inverse of L }
  for nmk:=0 to nm1 do begin
   k:=n-nmk-1;
   lmin:=MaxInt(ibeg,k);
   kl:=lmin*n+k-1;
   for l:=lmin to n-1 do begin
    Y^[l]:=Bi[kl];
    Bi[kl]:=0;
    inc(kl,n)
   end;
   kj:=mcol+k-1;
   while kj<maxdim do begin
    dsum:=-Bi[kj];
    lj:=(kj-k)+lmin+1;
    for l:=lmin to n-1 do begin
     dsum:=dsum+Y^[l]*Bi[lj];
     inc(lj)
    end;
    Bi[kj]:=-dsum;
    inc(kj,n)
   end
  end;
  jcol:=ncol-n;
  for nmj:=0 to nm1 do begin
   j:=n-nmj-2;
   k:=Indx^[j];
   if j<>k then begin
    ij:=jcol;
    ik:=k*n;
    for i:=0 to n-1 do begin
     inc(ij);
     {c:=Bi[ij]; Bi[ij]:=Bi[ik]; Bi[ik]:=c;}
     Bi.SwapCells(ij,ik);
     inc(ik)
    end
   end;
   dec(jcol,n)
  end;
 end;

begin
 eps0:=Tiny_IEEEExt;
 Errmn:=10*eps0; { the smallest relative error tolerance used }
 Errmx:=1E-5;    { the largest relative error tolerance used }
 xmax:=Big_IEEEExt; { the largest positive floating point number }
 m:=ConCnt-1;
 Iter:=0;
 icount:=0;
 mcheck:=MinInt(5,1+ConCnt div 15);
 OValue:=0;
 { check for input errors }
 ms:=LECnt+GECnt;
 if (ConCnt<2) or (XCnt<2) or (ms>ConCnt) then begin
  Result:=6; exit
 end;
 for i:=0 to m do
  if B[i]<0 then begin
   Result:=6; exit
  end;
 GetMem(Xb,ConCnt*SizeOf(float));
 FillChar(Xb^,ConCnt*SizeOf(float),0);
 GetMem(Y,ConCnt*SizeOf(float));
 GetMem(Basis,(ConCnt+XCnt)*SizeOf(integer));
 GetMem(Indx,ConCnt*SizeOf(integer));
 try
 rtol:=xmax;
 for i:=0 to XCnt-1 do
  if C[i]<>0 then rtol:=MinFloat(abs(C[i]),rtol);
 rtol:=Errmx*rtol;
 { formation of the IBasis and Basis arrays }
 ns:=XCnt+LECnt;
 n:=ns+GECnt;
 if not EBasis then goto 30;
 num:=n;
 for i:=0 to m do
  if IBasis[i]>=n then inc(num);
 goto 32;
22:
 if not EBasis then begin
  Result:=3;
  Proc220;
  exit
 end;
 EBasis:=False;
 Result:=0;
30:
 num:=XCnt+ConCnt;
 for i:=0 to m do IBasis[i]:=XCnt+i;
32:
 bflag:=0;
 FillChar(Basis^[0],n*SizeOf(integer),0);
 for i:=0 to m do Basis^[IBasis[i]]:=1;
 if not EBasis then begin
  { calculation of Xb and Bi when EBasis=False }
  Error:=Errmn;
  Bi.Clear;
  for j:=0 to m do begin
   Xb^[j]:=B[j];
   Bi[j,j]:=1
  end;
  if GECnt=0 then goto 630;
  for j:=LECnt to ms-1 do begin
   Xb^[j]:=-Xb^[j];
   Bi[j,j]:=-1
  end;
  goto 601
 end;
100:
 { reorder the basis }
 ibeg:=0;
 iend:=m;
 for i:=0 to m do
  if IBasis[i]>=XCnt then begin
   Indx^[ibeg]:=IBasis[i];
   inc(ibeg)
  end
  else begin
   Indx^[iend]:=IBasis[i];
   dec(iend)
  end;
 if iend=m then goto 22;
 for i:=0 to m do IBasis[i]:=Indx^[i]; { IBasis[1:ConCnt]=Indx[1:ConCnt] }
 { reinversion of the basis matrix }
 for j:=0 to m do begin
  kj:=IBasis[j];
  if kj<XCnt then begin
   for i:=0 to m do Bi[i,j]:=A[i,kj]; { Bi[1:ConCnt,j]=A[1:ConCnt,kj] }
   continue
  end;
  l:=kj-XCnt;
  Bi.FillCol(0,m,j,0); { Bi[1:ConCnt,j]=0 }
  if (kj<ns) or (kj>=n) then Bi[l,j]:=1 else Bi[l,j]:=-1
 end;
 icount:=0;
 Croutl(TFloatArray(Bi),iend+1,ierr);
 if ierr<>0 then goto 580;
 { check the accuracy of Bi and reset rerr }
 bnorm:=0;
 for j:=0 to m do begin
  kj:=IBasis[j];
  if kj<XCnt then begin
   total:=0;
   for i:=0 to m do total:=total+abs(A[i,kj])
  end
  else total:=1;
  bnorm:=MaxFloat(bnorm,total);
 end;
 binorm:=0;
 for j:=0 to m do begin
  total:=0;
  for i:=0 to m do total:=total+abs(Bi[i,j]);
  binorm:=MaxFloat(binorm,total)
 end;
 Error:=MaxFloat(Errmn,eps0*bnorm*binorm);
 if Error>1E-2 then goto 580;
 bflag:=0;
 { recalculation of Xb }
 for i:=0 to m do begin
  dsump:=0; dsumn:=0;
  for l:=0 to m do begin
   dt:=Bi[i,l]*B[l];
   if dt>0 then dsump:=dsump+dt else dsumn:=dsumn+dt;
  end;
  Xb^[i]:=dsump+dsumn;
  s:=dsump;
  t:=dsumn;
  tol:=Errmx*MaxFloat(s,-t);
  if abs(Xb^[i])<tol then Xb^[i]:=0
 end;
 goto 601;
200:
 { find the next vector A(--,jp) to be inserted into the basis }
 jp:=-1;
 rmin:=0;
 if Nstep=3 then rmin:=-rtol;
 for j:=0 to XCnt-1 do begin
  if (Basis^[j]<>0) or (X[j]>=rmin) then continue;
  jp:=j;
  rmin:=X[j]
 end;
 if n<>XCnt then begin
  rmin:=rmin*1.1;
  for j:=XCnt to n-1 do begin
   if (Basis^[j]<>0) or (X[j]>=rmin) then continue;
   jp:=j;
   rmin:=X[j]
  end;
 end;
 if jp<>-1 then goto 300;
 if nstep<2 then goto 800;
 if nstep=2 then begin
  { completion of the nstep=2 case }
  for i:=0 to m do begin
   if IBasis[i]<n then continue;
   if Xb^[i]>0 then goto 800
  end;
  goto 680;
 end;
 { completion of the nstep=3 case }
 if Error>1E-2 then begin
  if icount>=5 then goto 100;
  Result:=5{1};
 end
 else Result:=0;
 goto 800;

 { if MaxIter iterations have not been performed then begin the next iteration.
   compute the jp-th column of Bi*A and store it in Y }
300:
 if iter>=MaxIter then begin
  Result:=2;
  Proc220;
  exit
 end;
 inc(iter);
 inc(icount);
 if jp>=ns then begin
  l:=jp-XCnt;
  for i:=0 to m do Y^[i]:=-Bi[i,l]
 end
 else
 if jp>=XCnt then begin
  l:=jp-XCnt;
  for i:=0 to m do Y^[i]:=Bi[i,l]
 end
 else begin
  nrow:=-1;
  amax:=0;
  for i:=0 to m do begin
   if A[i,jp]=0 then continue;
   inc(nrow);
   Indx^[nrow]:=i;
   amax:=MaxFloat(abs(A[i,jp]),amax)
  end;
  if nrow=-1 then begin
   Result:=4;
   Proc220;
   exit
  end;
  rerr1:=Errmx*amax;
  for i:=0 to m do begin
   dsum:=0;
   for ll:=0 to nrow do begin
    l:=Indx^[ll];
    dsum:=dsum+Bi[i,l]*A[l,jp];
   end;
   Y^[i]:=dsum;
   if abs(Y^[i])>=5E-3 then continue;
   bmax:=0;
   for l:=0 to m do bmax:=MaxFloat(abs(Bi[i,l]),bmax);
   tol:=rerr1*bmax;
   if abs(Y^[i])<tol then Y^[i]:=0
  end;
 end;
 for i:=0 to m do
  if Y^[i]<>0 then goto 360;
 X[jp]:=0;
 dec(Iter);
 Dec(icount);
 goto 200;
360:
 if nstep=2 then goto 430;
 if nstep>2 then goto 440;
 { finding the variable Xb[ip] to be made nonbasic for the nstep=1 case }
 npos:=-1;
 ip:=-1;
 eps:=0;
 epsi:=xmax;
 for i:=0 to m do begin
  if (Xb^[i]<0) or (Y^[i]<=0) then continue;
  ratio:=Xb^[i]/Y^[i];
  if ratio<epsi then begin
   epsi:=ratio;
   npos:=0;
   Indx^[0]:=i;
   continue
  end
  else
  if ratio>epsi then continue;
  inc(npos);
  Indx^[npos]:=i
 end;
 if npos=-1 then begin
  for i:=0 to m do begin
   if (Xb^[i]>=0) or (Y^[i]>=0) then continue;
   ratio:=Xb^[i]/Y^[i];
   if ratio<eps then continue;
   eps:=ratio;
   ip:=i
  end;
  goto 500
 end;
 if epsi<>0 then begin
  for i:=0 to m do begin
   if (Xb^[i]>=0) or (Y^[i]>=0) then continue;
   ratio:=Xb^[i]/Y^[i];
   if (ratio>epsi) or (ratio<eps) then continue;
   eps:=ratio;
   ip:=i
  end;
  if ip<>-1 then goto 500
 end;
460:
 { tie breaking procedure }
 ip:=Indx^[0];
 if npos=0 then goto 500;
 ip:=-1;
 bmin:=xmax; cmin:=xmax;
 for ii:=0 to npos do begin
  i:=Indx^[ii];
  l:=IBasis[i];
  if l<XCnt then begin
   if C[l]<=0 then cmin:=MinFloat(0,cmin);
   if C[l]>cmin then continue;
   imin:=i;
   cmin:=C[l]
  end
  else begin
   if l>=n then begin
    ip:=i;
    goto 500
   end;
   lrow:=l-XCnt;
   s:=B[lrow];
   if lrow>=LECnt then begin
    s:=-s;
    bmin:=MinFloat(0,bmin);
   end;
   if s>bmin then continue;
   ip:=i;
   bmin:=s
  end
 end;
 if (cmin<=0) or (ip=-1) then ip:=imin;
500:
 { transformation of Xb }
 if Xb^[ip]<>0 then begin
  cons:=Xb^[ip]/Y^[ip];
  for i:=0 to m do begin
   s:=Xb^[i];
   Xb^[i]:=Xb^[i]-cons*Y^[i];
   if Xb^[i]>=0 then continue;
   if (s>=0) or (Xb^[i]>=Errmx*s) then Xb^[i]:=0
  end;
  Xb^[ip]:=cons
 end;
 { transformation of Bi }
 for j:=0 to m do begin
  if Bi[ip,j]=0 then continue;
  cons:=Bi[ip,j]/Y^[ip];
  for i:=0 to m do Bi[i,j]:=Bi[i,j]-cons*Y^[i];
  Bi[ip,j]:=cons
 end;
 { updating IBasis and Basis }
 iout:=IBasis[ip];
 IBasis[ip]:=jp;
 Basis^[iout]:=0;
 Basis^[jp]:=1;
 if iout>=n then dec(num);
 { check the accuracy of Bi and reset rerr }
 if Error<=1E-2 then begin
  k:=0;
  for j:=0 to m do begin
   kj:=IBasis[j];
   if kj>=XCnt then continue;
   total:=0;
   for i:=0 to m do total:=total+Bi[j,i]*A[i,kj]; {Dot_Product(Bi[j,1:ConCnt],A[1:ConCnt,kj]);}
   Error:=MaxFloat(Error,abs(1-total));
   inc(k);
   if k>=mcheck then break
  end;
  if Error<=1E-2 then goto 600;
 end;
 { the accuracy criteria are not satisfied }
 if icount<5 then goto 600;
 bflag:=1;
 goto 100;
580:
 if iter=0 then begin
  Result:=6; exit
 end;
 if bflag=0 then begin
  Result:=3;
  Proc220;
  exit
 end;
 bflag:=0;
 ip:=0;
 while ip<=m do begin
  if jp=IBasis[ip] then break;
  inc(ip)
 end;
 IBasis[ip]:=iout;
 Basis^[jp]:=0;
 Basis^[iout]:=1;
 if iout>=n then inc(num);
 goto 100;
430:
 { finding the variable Xb[ip] to be made nonbasic for the nstep=2 case }
 npos:=-1;
 epsi:=xmax;
 for i:=0 to m do begin
  if Y^[i]<=0 then continue;
  ratio:=Xb^[i]/Y^[i];
  if ratio<epsi then begin
   epsi:=ratio;
   npos:=0;
   Indx^[0]:=i
  end
  else
  if ratio>epsi then continue;
  inc(npos);
  Indx^[npos]:=i
 end;
 goto 450;
440:
 { finding the variable Xb[ip] to be made nonbasic for the nstep=3 case }
 npos:=-1;
 epsi:=xmax;
 for i:=0 to m do begin
  if Y^[i]<0 then begin
   if IBasis[i]<n then continue;
   ip:=i;
   goto 500
  end
  else
  if Y^[i]>0 then begin
   ratio:=Xb^[i]/Y^[i];
   if ratio<epsi then begin
    epsi:=ratio;
    npos:=0;
    Indx^[0]:=i
   end
   else
   if ratio>epsi then continue;
   inc(npos);
   Indx^[npos]:=i
  end;
 end;
450:
 if npos<>-1 then goto 460;
 if icount>=5 then goto 100;
 Result:=4;
 Proc220;
 exit;
600:
 { set up the R array for the nstep=1 case }
 if nstep=2 then goto 630;
 if nstep>2 then goto 700;
601:
 for j:=0 to m do
  if Xb^[j]<0 then goto 610;
 goto 630;
610:
 nstep:=1;
 i:=-1;
 for l:=0 to m do begin
  if Xb^[l]>=0 then continue;
  inc(i);
  Indx^[i]:=l;
 end;
 for j:=0 to m do begin
  dsump:=0; dsumn:=0;
  for ll:=0 to i do begin
   l:=Indx^[ll];
   if Bi[l,j]<0 then dsumn:=dsumn+Bi[l,j]
   else
   if Bi[l,j]>0 then dsump:=dsump+Bi[l,j];
  end;
  Y^[j]:=dsump+dsumn;
  s:=dsump;
  t:=dsumn;
  tol:=Errmx*MaxFloat(s,-t);
  if abs(Y^[j])<tol then Y^[j]:=0
 end;
 goto 650;
630:
 { setup the R array for the nstep=2 case }
 if n=num then goto 680;
 nstep:=2;
 i:=-1;
 for l:=0 to m do begin
  if IBasis[l]<n then continue;
  inc(i);
  Indx^[i]:=l
 end;
 for j:=0 to m do begin
  dsump:=0; dsumn:=0;
  for ll:=0 to i do begin
   l:=Indx^[ll];
   if Bi[l,j]<0 then dsumn:=dsumn+Bi[l,j]
   else
   if Bi[l,j]>0 then dsump:=dsump+Bi[l,j];
  end;
  Y^[j]:=-(dsump+dsumn);
  s:=dsump;
  t:=dsumn;
  tol:=Errmx*MaxFloat(s,-t);
  if abs(Y^[j])<tol then Y^[j]:=0
 end;
650:
 for j:=0 to XCnt-1 do
  if Basis^[j]=0 then begin
   tmp:=0;
   for i:=0 to m do tmp:=tmp+Y^[i]*A[i,j];
   X[j]:=tmp
  end
  else X[j]:=0;
660:
 if XCnt<>ns then begin
  for j:=XCnt to ns-1 do begin
   X[j]:=0;
   if Basis^[j]<>0 then continue;
   X[j]:=Y^[j-XCnt]
  end
 end;
 if ns=n then goto 200;
 for j:=ns to n-1 do begin
  X[j]:=0;
  if Basis^[j]<>0 then continue;
  X[j]:=-Y[j-XCnt]
 end;
 goto 200;
680:
 { setup the R array for the nstep=3 case }
 nstep:=3;
 for j:=0 to m do begin
  dsum:=0;
  for l:=0 to m do begin
   ll:=IBasis[l];
   if ll<XCnt then dsum:=dsum+C[ll]*Bi[l,j]
  end;
  Y^[j]:=dsum
 end;
 for j:=0 to XCnt-1 do begin
  X[j]:=0;
  if Basis^[j]<>0 then continue;
  dsum:=-C[j];
  for i:=0 to m do dsum:=dsum+Y^[i]*A[i,j];
  X[j]:=dsum;
  if dsum>=0 then continue;
  tol:=Errmx*abs(C[j]);
  if abs(X[j])<tol then X[j]:=0
 end;
 goto 660;
700:
 { update the R array for the nstep=3 case }
 cons:=X[jp];
 for j:=0 to XCnt-1 do begin
  if Basis^[j]<>0 then X[j]:=0
  else begin
   total:=0;
   for i:=0 to m do total:=total+Bi[ip,i]*A[i,j];
   X[j]:=X[j]-cons*total;
   if X[j]>=0 then continue;
   tol:=Errmx*abs(C[j]);
   if abs(X[j])<tol then X[j]:=0
  end
 end;
 if XCnt<>ns then begin
  for j:=XCnt to ns-1 do begin
   if Basis^[j]<>0 then X[j]:=0 else X[j]:=X[j]-cons*Bi[ip,j-XCnt]
  end;
 end;
 if ns=n then goto 200;
 for j:=ns to n-1 do begin
  if Basis^[j]<>0 then X[j]:=0 else X[j]:=X[j]+cons*Bi[ip,j-XCnt]
 end;
 goto 200;
 { refine Xb and stote the result in Y }
800:
 FillChar(Y^,ConCnt*SizeOf(float),0);
 ll:=-1;
 for j:=0 to m do begin
  kj:=IBasis[j];
  if kj<XCnt then begin
   inc(ll);
   Indx^[ll]:=j;
   continue
  end;
  l:=kj-XCnt;
  if (kj<ns) or (kj>=n) then Y^[l]:=Xb^[j] else Y^[l]:=-Xb^[j]
 end;
 if ll=-1 then
  for i:=0 to m do X[i]:=B[i]-Y^[i]
 else
  for i:=0 to m do begin
   dsum:=Y^[i];
   for ii:=0 to ll do begin
    j:=Indx^[ii];
    kj:=IBasis[j];
    dsum:=dsum+A[i,kj]*Xb^[j]
   end;
   X[i]:=B[i]-dsum
  end;
 rerr1:=MinFloat(Errmx,Error);
 for i:=0 to m do begin
  Y^[i]:=0;
  if Xb^[i]<0 then begin
   sgn:=-1;
   dsump:=0;
   dsumn:=Xb^[i]
  end
  else
  if Xb^[i]>0 then begin
   sgn:=1;
   dsump:=Xb^[i];
   dsumn:=0
  end
  else continue;
  for l:=0 to m do begin
   dt:=Bi[i,l]*X[l];
   if dt>0 then dsump:=dsump+dt else dsumn:=dsumn+dt;
  end;
  w:=dsump+dsumn;
  if w=0 then continue;
  if sgn<>ForSign(1,w) then continue;
  s:=dsump;
  t:=dsumn;
  tol:=rerr1*MaxFloat(s,-t);
  if abs(w)>tol then Y^[i]:=w
 end;
 case nstep of
  1:begin
   { check the refinement (nstep=1) }
   for i:=0 to m do begin
    if Y^[i]<0 then begin
     if Y^[i]<-Errmx then begin
      if icount>=5 then goto 100;
      Result:=5{1};
      Proc220;
      exit
     end;
     Y^[i]:=0
    end;
    Xb^[i]:=Y^[i]
   end;
   goto 630;
  end;
  2: begin
   { check the refinement (nstep=2) }
   for i:=0 to m do begin
    if IBasis[i]>=n then begin
     if Y^[i]>Errmx then begin
      if icount>=5 then goto 100;
      Result:=5{1};
      Proc220;
      exit
     end;
     Y^[i]:=0
    end;
    Xb^[i]:=Y^[i]
   end;
   goto 680;
  end;
  else begin
   { compute OValue (nstep=3) }
   dsum:=0;
   for i:=0 to m do begin
    j:=IBasis[i];
    if j<XCnt then dsum:=dsum+C[j]*Y^[i];
    Xb^[i]:=Y^[i]
   end;
   OValue:=dsum;
   Proc220;
   exit
  end;
 end; { case }
 finally
  Done
 end
end;

end.

procedure TForm1.TestLinProg;
var i,j,Res,XDim:integer; ConCnt,XCnt,LECnt,GECnt:integer; EBasis:boolean;
 A:TGFloatMatrix; B:TFloatArray; C:TFloatArray; IBasis:TIntArray; X:TFloatArray;
 v,OValue:extended; Iter:longint; Error:double;
 MaxIter:longint; Bi:TGFloatMatrix; s:string;
begin
 (*
 ConCnt:=2;
 XCnt:=2;
 LECnt:=2;
 GECnt:=0;
 *)
 ConCnt:=SpinEdit2.Value;
 XCnt:=SpinEdit1.Value;
 LECnt:=SpinEdit3.Value;
 GECnt:=SpinEdit4.Value;
 EBasis:=False;
 MaxIter:=100;

 A:=TGFloatMatrix.Create(ConCnt,XCnt);
 B:=TFloatArray.Create(ConCnt);
 C:=TFloatArray.Create(XCnt);
 IBasis:=TIntArray.Create(ConCnt);
 XDim:=XCnt+LECnt+GECnt;
 X:=TFloatArray.Create(XDim);
 Bi:=TGFloatMatrix.Create(ConCnt,ConCnt);

 for i:=0 to ConCnt-1 do begin
  s:=Grid1.Cells[0,i+1];
  val(s,v,Res);
  B[i]:=v;
  if i<XCnt then begin
   s:=Grid2.Cells[0,i];
   val(s,v,Res);
   C[i]:=v;
  end;
  for j:=0 to XCnt-1 do begin
   s:=Grid1.Cells[j+1,i+1];
   val(s,v,Res);
   A[i,j]:=v
  end
 end;

 (*
 A.InitFromConstArray([2,3,4,1{1,-1,1,0,1,4,0,1}{3,2,4,5}]);
 B.InitFromConstArray([9,6{20,20,10,5}{1700,1600}]);
 C.InitFromConstArray([6,2{3,4}{2,4}]);
 *)
 try
  Res:=Simplex(A,B,C,ConCnt,XCnt,EBasis,IBasis,X,OValue,Iter,MaxIter,LECnt,GECnt,Bi,Error);
  Memo1.Text:=IntToStr(Res);
  Memo1.Lines.Add(FloatToStr(OValue));
  Memo1.Lines.Add('Iters='+IntToStr(Iter));
  for i:=0 to XCnt-1 do Memo1.Lines.Add('x['+IntToStr(i+1)+']='+FloatToStr(X[i]));
  Memo1.Lines.Add('constrains:');
  for i:=0 to ConCnt-1 do begin
   v:=0;
   for j:=0 to XCnt-1 do v:=v+A[i,j]*X[j];
   Memo1.Lines.Add(FloatToStr(v)+' ('+FloatToStr(B[i])+')');
  end;
  Memo1.Lines.Add('Rel Error='+FloatToStr(Error));
 finally
  A.Free;
  B.Free;
  C.Free;
  IBasis.Free;
  Bi.Free;
 end;
end;

 

Это сообщение отредактировал(а) maxim1000 - 26.12.2007, 11:38
  Вверх
Belo4ka
Дата 26.12.2007, 10:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 26.12.2007

Репутация: нет
Всего: нет



Можете помочь с модифицированный симплекс-методом! Очень надо! помогите плиз!!!
PM MAIL   Вверх
Belo4ka
Дата 27.12.2007, 00:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 26.12.2007

Репутация: нет
Всего: нет



Дорогие специалисты! помогите плиз с исходниками модифицированного симплекс-метода. 
PM MAIL   Вверх
alexey111
Дата 1.3.2011, 17:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 1.3.2011

Репутация: нет
Всего: нет




Модератор: Сообщение скрыто.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, maxim1000.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Алгоритмы | Следующая тема »


 




[ Время генерации скрипта: 0.0799 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.