Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Лабораторная работа №8. Решение задачи нелинейного программирования методами Лагранжа и приведенного градиента Вулфа




 При решении использовать методы неопределенных множителей Лагранжа, приведенного градиента Вулфа.

Пример.

Требуется найти максимальное значение заданной целевой функции  при заданных условиях:

 

6.8.1 Метод неопределенных множителей Лагранжа

        Метод реализован в Lagrang.pas.

 

Входные данные.

Описание типов.

 

TKvadrF = Record c : Array of Array of Real; D : Array of Real; End – запись для хранения целевой функции.

TOgr = Record A : Array of Array of Real; B : Array of Real; End запись для хранения системы ограничений.

TSyst = Array of Array of Real – для хранения системы ограничений при переходе к задаче линейного программирования.

Используемые глобальные переменные:

- KF : TKvadrF – хранит целевую функцию;

- Ogr : TOgr – хранит систему ограничений.

- m,n : Integer – количество ограничений и переменных соответственно;

- Syst : TSyst – хранит новую систему ограничений.

Описаны следующие функции.

Функция Function Lagr(Var X : Array of Real;Var Res : Byte) : Real – реализует метод неопределенных множителей Лагранжа. Возвращает оптимальное значение функции.


Параметры функции:

- X – на выходе получает оптимальную точку;

- Res –признак решения (на выходе возвращает 1, если задача решена и ноль, если задача неразрешима).

Процедура Procedure SM (Syst: TSyst; m, n: Integer; Var X: Array of Real; Var Res: Byte) – решает задачу линейного программирования методом искусственного базиса.

Параметры функции:

- Syst – система ограничений;

- m и n – количество ограничений и переменных соответственно;

- X – на выходе содержит оптимальную точку;

- Res – признак решения (на выходе возвращает 1, если задача решена и ноль, если задача неразрешима).

Текст программы.

{Метод неопределенных множителей Лагранжа}

{Расчитан на решение задач выпуклого программирования. В вызывающей программе

должна быть определена квадратичная форма KF, ограничения Ogr, а также пере-

менные n и m, хранящие число переменных и ограничений.}

unit Lagrang;

interface

uses dialogs,SysUtils;

Type

{Тип квадратичная форма.Задается целевая функция}

TKvadrF = Record

c : Array of Array of Real;

D : Array of Real;

End;

{Тип ограничений.Задаются ограничения для данной задачи}

TOgr = Record

A : Array of Array of Real;

B : Array of Real;

End;

 

{Производные функции Лагранжа по всем переменным.}

TSyst = Array of Array of Real;

 

Var

{KF,Ogr,m и n необходимо определить в вызывающей програмее}

KF : TKvadrF;

Ogr : TOgr;

m,n : Integer;//m - количество ограничений,

                     //n - количество переменных

Syst : TSyst;

 

{Основная функция}

Function Lagr(Var X : Array of Real;Var Res : Byte) : Real;

//X - в эту переменную вернется оптимальное значение неизвестных

//Res - вернет 1, если задача решена, 0 - если неразрешима

Procedure SM(Syst : TSyst;m,n : Integer;Var X : Array of Real;Var Res : Byte);

 

implementation

 

Procedure SM;

Var I,J : Integer;

SystNew : TSyst;//Новая система с большим количеством

                           // переменных чем в Syst

mm,nn : Integer;//Новое количество переменных и ограничений

A : Array of Array of Real;//Для хранения всех базисов

Basis : Array of Integer;//Хранит номера векторов, вошедших в базис

MV,Cbas,B,BCopy,Ocenki : Array of Real;

                  //MV - Хранит коэффициены при каждой переменной в

                  //целевой функции

                 //CBas - Содержит коэффициенты при соответствующих

                 //неизвестных в целевой функции

                        //B - хранится опорный план

                        //BCopy - временная переменная для вычисления B

                        //Ocenki - хранит оценки

Optim,ImeetResh : Boolean;

                 //Optim - хранит информацию, оптимален ли план

                 //ImeetResh - Хранит информацию, имеет ли задача решение

min : Real;//вспомогательнач переменная

VedStr,VedCol : Integer;

               //VedCol - ведущий столбец

               //VedStr - ведущая строка

Begin

SetLength(SystNew,n+m,n+m+n+m+n+1);//Определяется размернсть с учетом

                              //дополнительных неизвестных в задаче

For I:=0 to n+m-1 do For J:=0 to n+m-1 do SystNew[I,J]:=Syst[I,J];

                                 //Заносятся старые значения

 

For I:=m+n to m+n+n-1 do SystNew[I-m-n,I]:=-1;//Вводятся переменные Vi, для

                              //перехода к равенству в производных по x 

For I:=m+n+n to m+n+n+m-1 do SystNew[I-n-n,I]:=1;//Вводятся переменные Wi, для

                           //перехода к равенству в производных по Lambda

For I:=m+n+n+m to m+n+n+m+n-1 do SystNew[I-m-n-n-m,I]:=1;

                            //Вводятся переменные

                            //Zi, для введения искусственного базиса

For I:=0 to n+m-1 do SystNew[I,n+m+n+m+n]:=Syst[I,n+m];//Копируются правые части

 

mm:=n+m;           //Определяется новая размерность

nn:=n+m+n+m+n;

 

SetLength(A,nn,mm);

For I:=0 to nn-1 do //Заполнение матрицы базисов

For J:=0 to mm-1 do A[I,J]:=SystNew[J,I];

 

SetLength(Basis,mm);

For I:=0 to mm-1 do Basis[I]:=nn+I-mm;//В качестве базиса берутся искуственно

                       //введенные вектора, то есть введенные последними

SetLength(MV,nn);

For I:=0 to nn-n-1 do MV[I]:=0; //Коэффициенты в новой целевой функции отличны

For I:=nn-n to nn-1 do MV[I]:=-1;//от нуля только при искуственных переменных

 

SetLength(Cbas,mm);

For I:=0 to mm-1 do Cbas[I]:=MV[Basis[I]];//Вводятся коэффициенты при переменных,

                                   //входящих в базисное решение

SetLength(B,mm);

For I:=0 to mm-1 do B[I]:=Syst[I,mm];//Начальное опорное решение

SetLength(BCopy,mm);

 

SetLength(Ocenki,nn);

For I:=0 to nn-1 do {Вычисление оценок}

Begin

Ocenki[I]:=0;

For J:=0 to mm-1 do Ocenki[I]:=Ocenki[I]+Cbas[J]*A[I,J];

Ocenki[I]:=Ocenki[I]-MV[I];

End;

 

ImeetResh:=True;

For I:=0 to nn-1 do //Выясняется, есть ли решение у данной задачи

If Ocenki[I]<0 Then

Begin

Optim:=False;//Optim используется как вспомогательная переменная

For J:=0 to mm-1 do Optim:=Optim Or (A[I][J]>0);

ImeetResh:=ImeetResh and Optim;

End;

 

Optim:=True;

for I:=0 to nn-1 do If Ocenki[I]<0 Then Begin Optim:=False;Break;End;

                                //Проверка на оптимальность

If ImeetResh Then//Если имеет решение...

Begin

While (Not Optim) do//Пока не оптимально ...

Begin

min:=0;

For I:=1 to nn-1 do//Вычисление минимальной оценки

If Ocenki[I]<Ocenki[Round(min)] Then min:=I;

VedCol:=Round(Min);//Ведущей столбец там, где оценка наименьшая

 

For I:=0 to mm-1 do// Находится первый положительный элемент в ведущем столбце

If A[VedCol][I]>0 Then Begin min:=I;Break;End;

 

I:=Round(min+1);

While I<=mm-1 do//Находится ведущая строка.

                    //Она будет там, где отношение базисного

Begin    //элемента к положительному элементу ведущего

                    //столбца будет минимальным

If A[VedCol][I]>0 Then                                     

   If (B[I]/A[VedCol][I])<(B[Round(min)]/A[VedCol][Round(min)]) Then Begin min:=I;End;

Inc(I);

End;

VedStr:=Round(min);

 

BCopy:=Copy(B);

For I:=0 to mm-1 do //Вычисление нового опроного решения

If I<>VedStr Then// Если строка не ведущая, то вычисляется по

                               // правилу прямоугольника

              B[I]:=(BCopy[I]*A[VedCol][VedStr]-

              A[VedCol][I]*BCopy[VedStr])/A[VedCol][VedStr]

              Else//Иначе вычисляется делением на ведущий элемент

              B[I]:=BCopy[I]/A[VedCol][VedStr];

 

For I:=0 to mm-1 do//Вычисление новых векторов A

   Begin

If I<>VedStr Then//Если строка не ведущая

   For J:=0 to nn-1 do

   Begin//Правило прямоугольника

   A[J][I]:=(A[J][I]*A[VedCol][VedStr]-

   A[VedCol][I]*A[J][VedStr])/A[VedCol][VedStr];

   End;

End;

 

{Вычисление новых значений в ведущей строке}

For I:=0 to nn-1 do If I<>VedCol Then A[I][VedStr]:=A[I][VedStr]/A[VedCol][VedStr];

A[VedCol][VedStr]:=1;

Basis[VedStr]:=VedCol;//Замена в базисе

Cbas[VedStr]:=MV[VedCol];//Новое значение в векторе Cbas

 

For I:=0 to nn-1 do//Вычисление новых оценок

Begin

Ocenki[I]:=0;

For J:=0 to mm-1 do Ocenki[I]:=Ocenki[I]+Cbas[J]*A[I,J];

Ocenki[I]:=Ocenki[I]-MV[I];

End;

 

Optim:=True;//Проверка плана на оптимальность

for I:=0 to nn-1 do If Ocenki[I]<0 Then Begin Optim:=False;Break;End;

 

End;{While}

 

For I:=0 to High(Basis) do If Basis[I]<=n-1 Then X[Basis[I]]:=B[I];

// For I:=0 to n-1 do X[I]:=B[I];//Оптимальная точка

Res:=1;//Задача решена

End

Else

Res:=0;//Задача неразрешима

 

End;

 

Function Lagr;

Var I,J : Integer;

Begin

SetLength(Syst,n+m,n+m+1);{n+m так как производные по всем переменным x дают n,   а по всем переменным Lambda дают m. Так как будут

храниться и правые части, то вводится +1}

{Заполняется система производных}

For I:=0 to n-1 do

Begin

For J:=0 to n-1 do

if I<>J Then

Begin

  Syst[I,J]:=-KF.c[i,j];//Минус берется, т.к. в дальнейшем

                                   //придется менять знак

End

Else

Begin

Syst[I,I]:=-2*KF.c[I,I];//Вычисление производных второго порядка.

End;

For J:= n to m+n-1 do {Вычисляются производные подфункций вида Lambda*f(X1..Xn)}

  Syst[I,J]:=Ogr.A[J-n,I];

End;

 

For I:=n to m+n-1 do

Begin

For J:= 0 to n-1 do

  Syst[I,J]:=Ogr.A[I-n,J];//Минус не берется, т.к. в дальнейшем

                                        //придется менять знак

 

For J:=n to m+n-1 do

  Syst[I,J]:=0;

End;

 

For I:=0 to n-1 do Syst[I,m+n]:=KF.D[I];//Формируются правые части

                                  // системы в произвоных по x

For I:=n to m+n-1 do Syst[I,m+n]:=Ogr.B[I-n];//Формируются правые

                                        // части системы в произвоных по Lambda

SM(Syst,m,n,X,Res);//Вызывается симплекс метод для дальнейшего

                             // решения задачи

Result:=0;

For I:=0 to n-1 do//Вычисление оптимального значения функции

For J:=I to n-1 do

Result:=Result+KF.C[I,J]*X[I]*X[J];

 

For I:=0 to n-1 do Result:=Result+KF.D[I]*X[I];

End;

end.

 

Результат работы программы.

Оптимальное решение: x=(0.67,0.67).

Оптимальное значение функции: 0,44.


6.8.2 Метод приведенного градиента Вулфа

 

Метод реализован в модуле Wolf.pas.

         Описание типов.

TPoint = Array of Real;

     TPurposeFunction = Function (P: TPoint): Real;

TVector = Array of Real;

TMatrix = Array of Array of Real;

TProisvod = Array of Function(P : TPoint) : Real.

     Используемые глобальные переменные.

P: TPoint – хранит текущую точку.

PF: TPurposeFunction – хранит целевую функцию.

Proisvod: TProisvod – массив производных.

d: TVector – служебная переменная.

cc: TMatrix – первая часть квадратичной формы.

dd: TVector – вторая часть квадратичной формы.

Описание функций.

Function Search (n, m: Integer; A: TMatrix): Real – реализует метод Вулфа.

Параметры функции.

m – количество ограничений.

n – количество переменных.

A –матрица коэффициентов системы ограничений.

Текст программы.

unit Wolf;

interface

Type TPoint = Array of Real;

TPurposeFunction = Function(P : TPoint) : Real;

TVector = Array of Real;

TMatrix = Array of Array of Real;

TProisvod = Array of Function(P : TPoint) : Real;

Var P : TPoint;

PF : TPurposeFunction;

Proisvod : TProisvod;

d : TVector;

cc : TMatrix;

dd : TVector;

 

Function Search(n,m : Integer;A : TMatrix) : Real;

 

implementation

Uses Ravnomer_Search;

 

Function Optim(d : TVector) : Boolean;

Var I : Integer;

Begin

Result:=True;

For I:=0 to High(d) do Result:=Result and (d[I]=0);

 

End;

 

Procedure ObrMat (N : Byte; A : TMatrix; Var B : TMatrix );

 Var i,j,k : Byte;

Base : real;

Begin

 for i:=0 to N-1 do

for j:=0 to N-1 do if i=j then B[i][j]:=1 else B[i][j]:=0;

 

 for k:=0 to N-1 do

begin

Base := A[k][k];

for i:=0 to N-1 do

for j:=0 to N-1 do

begin

if (i<>k) and (j>k) then A[i][j] := A[i][j] - A[k][j]*A[i][k]/Base;

if i<>k then B[i][j] := B[i][j] - B[k][j]*A[i][k]/Base;

end;

if Base<>1 then

for i:=0 to N-1 do

begin

     A[k][i] := A[k][i]/Base;

  B[k][i] := B[k][i]/Base;

end;

for i:=0 to N-1 do if i<>k then A[i][k] := 0;

end;

 End;

 

Function func(x : Real) : Real;

Var I,J : Integer;

Begin

Result:=0;

For I:=0 to High(P)-1 do

For J:=I to High(P)-1 do Result:=Result+cc[I,J]*(P[I]+d[I]*x)*(P[J]+d[J]*x);

For I:=0 to High(P)-1 do Result:=Result+dd[I]*(P[I]+x*d[I]);

End;

 

Function Search;

Var BBObr : TMatrix;

BB,NN,MatrixTemp : TMatrix;

I,J,k,l : Integer;

I1 : Array of Integer;

I11 : Set of Byte;

GradF,GradBF,Multipl,rT,dB,dN : TVector;

Sum,Lambda : Real;

f : Ravnomer_Search.FType;

Res : Byte;

PTemp : TPoint;

 

Begin

SetLength(BB,m,m);

SetLength(BBObr,m,m);

SetLength(NN,m,n-m);

SetLength(I1,m);

SetLength(PTemp,n);

SetLength(GradF,n);

SetLength(GradBF,m);

SetLength(Multipl,n);

SetLength(rT,n);

SetLength(dB,m);

SetLength(dN,n-m);

SetLength(d,n);

SetLength(MatrixTemp,m,n-m);

 

 

f:=func;

PTemp:=Copy(P);

I11:=[];

For I:=0 to m-1 do

Begin

I1[I]:=0;

For J:=0 to n-1 do If PTemp[J]>PTemp[I1[I]] Then Begin

                                              I1[I]:=J;

                                              End;

PTemp[I1[I]]:=-3000000;

I11:=I11+[I1[I]];

End;

k:=0;l:=0;

For I:=0 to n-1 do

If I in I11 Then

  Begin

   For J:=0 to m-1 do

   Begin

   BB[J][k]:=A[J][I];

   End;

Inc(k);

End

Else

Begin

   For J:=0 to m-1 do

   Begin

   NN[J][l]:=A[J][I];

   End;

Inc(l);

End;

 

ObrMat(m,BB,BBObr);

 

For I:=0 to n-1 do GradF[I]:=Proisvod[I](P);

 

k:=0;

For I:=0 to n-1 do

If I in I11 Then

Begin

GradBF[k]:=Proisvod[I](P);

Inc(k);

End;

 

For I:=0 to m-1 do

Begin

Sum:=0;

For J:=0 to m-1 do Sum:=Sum+GradBF[J]*BBObr[J][I];

Multipl[I]:=Sum;

End;

 

For I:=0 to n-1 do

Begin

Sum:=0;

For J:=0 to m-1 do Sum:=Sum+Multipl[J]*A[J][I];

rT[I]:=Sum;

End;

 

For I:=0 to n-1 do rT[I]:=GradF[I]-rT[I];

 

k:=0;

For I:=0 to n-1 do

If Not (I in I11) Then

Begin

If rT[I]<=0 Then Begin

             dN[k]:=-rT[I];

             End

             Else

             Begin

             dN[k]:=-P[I]*rT[I];

             End;

Inc(k);

End;

 

For I:=0 to m-1 do

For J:=0 to n-m-1 do

Begin

MatrixTemp[I,J]:=0;

For k:=0 to m-1 do MatrixTemp[I,J]:=MatrixTemp[I,J]+BBObr[I,k]*NN[k,J];

End;

 

For I:=0 to m-1 do

Begin

dB[I]:=0;

For J:=0 to n-m-1 do dB[I]:=dB[I]+MatrixTemp[I,J]*dN[J];

dB[I]:=-dB[I];

End;

 

k:=0;l:=0;

For I:=0 to n-1 do

If I in I11 Then

Begin

d[I]:=dB[k];

Inc(k);

End

Else

Begin

d[I]:=dN[l];

Inc(l);

End;

 

For I:=0 to n-1 do

If d[I]<0 Then Begin Lambda:=-P[I]/d[I];Break; End;

 

For I:=0 to n-1 do

If (d[I]<0) and (-P[I]/d[I]<Lambda) Then Lambda:=-P[I]/d[I];

 

Lambda:=Ravnomer_Search.Search(0,Lambda,100,f,Res,0.001);

 

For I:=0 to n-1 do P[I]:=P[I]+Lambda*d[I];

For I:=0 to n-1 do If abs(P[I])<0.0001 Then P[I]:=0;

 

While not Optim(d) do

Begin

 

PTemp:=Copy(P);

I11:=[];

For I:=0 to m-1 do

Begin

I1[I]:=0;

For J:=0 to n-1 do If PTemp[J]>PTemp[I1[I]] Then Begin

                                                I1[I]:=J;

                                                End;

PTemp[I1[I]]:=-3000000;

I11:=I11+[I1[I]];

End;

k:=0;l:=0;

For I:=0 to n-1 do

If I in I11 Then

   Begin

     For J:=0 to m-1 do

     Begin

     BB[J][k]:=A[J][I];

     End;

   Inc(k);

   End

  Else

   Begin

     For J:=0 to m-1 do

     Begin

     NN[J][l]:=A[J][I];

     End;

   Inc(l);

   End;

 

ObrMat(m,BB,BBObr);

 

For I:=0 to n-1 do GradF[I]:=Proisvod[I](P);

 

k:=0;

For I:=0 to n-1 do

If I in I11 Then

Begin

GradBF[k]:=Proisvod[I](P);

Inc(k);

End;

 

For I:=0 to m-1 do

Begin

Sum:=0;

For J:=0 to m-1 do Sum:=Sum+GradBF[J]*BBObr[J][I];

Multipl[I]:=Sum;

End;

 

For I:=0 to n-1 do

Begin

Sum:=0;

For J:=0 to m-1 do Sum:=Sum+Multipl[J]*A[J][I];

rT[I]:=Sum;

  End;

 

For I:=0 to n-1 do rT[I]:=GradF[I]-rT[I];

 

k:=0;

For I:=0 to n-1 do

If Not (I in I11) Then

Begin

If rT[I]<=0 Then Begin

               dN[k]:=-rT[I];

               End

               Else

               Begin

               dN[k]:=-P[I]*rT[I];

               End;

Inc(k);

End;

 

For I:=0 to m-1 do

For J:=0 to n-m-1 do

Begin

MatrixTemp[I,J]:=0;

For k:=0 to m-1 do MatrixTemp[I,J]:=MatrixTemp[I,J]+BBObr[I,k]*NN[k,J];

   End;

 

For I:=0 to m-1 do

Begin

dB[I]:=0;

For J:=0 to n-m-1 do dB[I]:=dB[I]+MatrixTemp[I,J]*dN[J];

dB[I]:=-dB[I];

End;

 

k:=0;l:=0;

For I:=0 to n-1 do

If I in I11 Then

Begin

d[I]:=dB[k];

Inc(k);

End

    Else

Begin

d[I]:=dN[l];

Inc(l);

End;

 

For I:=0 to n-1 do

If d[I]<0 Then Begin Lambda:=-P[I]/d[I];Break; End;

 

For I:=0 to n-1 do

If (d[I]<0) and (-P[I]/d[I]<Lambda) Then Lambda:=-P[I]/d[I];

 

Lambda:=Ravnomer_Search.Search(0,Lambda,100,f,Res,0.001);

 

For I:=0 to n-1 do P[I]:=P[I]+Lambda*d[I];

 

For I:=0 to n-1 do If abs(P[I])<0.0001 Then P[I]:=0;

For I:=0 to n-1 do If abs(d[I])<0.001 Then d[I]:=0;

End;{While}

Result:=1;

End;

end.

 

Результат работы программы.

Оптимальное решение: x=(0.669,0.671).

Оптимальное значение функции: 0,443.

 


Варианты заданий.

 

1.

  

2.

3.

4.

5.


6.

7.

8.

9.

10.  


11.

 

 

 

12.

 

 

 

13.

 

 

14.

 

 

  

15.

 

 

 

16.

  

  

 

17.

 

 

 

18.

 

 

 

19.

 

 

 

20.

 

 

 

21.

 

 

 


22.

 

 

 

23.

 

 

 

24.

 

 

25.

 

 

 

26.

 

  

   

27.

 

 

 


28.

 

 

 

29.

 

 

30.

 

 

  










Последнее изменение этой страницы: 2018-04-12; просмотров: 262.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...