Смекни!
smekni.com

Багатокритеріальна задача лінійного програмування (стр. 10 из 17)

Var ToMax: Boolean; Row, Col, CurWidth, DFuncRowNum: Integer;

Const sc_CurProcName='PrepareDFuncForSimplexMaximize';

Begin

CurWidth:=Length (Self. CurHeadRow);

DFuncRowNum:=Length (Self. CurHeadCol) – 1;

Case Self. CurHeadCol[DFuncRowNum].ElmType of {перевіряємо тип функції мети:}

bc_DestFuncToMax: ToMax:=True;

bc_DestFuncToMin: ToMax:=False;

Else{якщо заданий рядок виявився не функцією мети:}

Begin

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add (sc_CurProcName+

sc_CurRowNotMarkedAsDestFunc+IntToStr (DFuncRowNum+1));

PrepareDFuncForSimplexMaximize:=False; Exit;

End;

End;

{Готуємо умову для вирішування симплекс-методом максимізації:}

{Міняємо знаки у елементів рядка-заголовка, окрім знака останньої

комірки – то множник для стовпця правих частин. Це є

інтерпретацією перенесення усіх доданків у праву частину, і

форматом для виконання модифікованих Жорданових виключень:}

For Col:=0 to CurWidth-2 do

ChangeSignForValOrVarName (Self. CurHeadRow[Col]);

{Якщо треба шукати максимум, то множимо коефіцієнти функції мети

на -1 (окрім вільгого члена), бо помножили і усі x1…xn на -1.

Якщо треба мінімум, то ці коефіцієнти не множимо

(бо x1…xn вже помножені), але множимо вільний член функції. Тоді

отримаємо протилежну функцію, щоб знайти її максимум

(це протилежний мінімум заданої функції):}

Row:=Length (Self. CurHeadCol) – 1; {рядок функції мети}

If ToMax then

Begin

For Col:=0 to CurWidth-2 do {коефіцієнти функції мети міняють знаки:}

Self. CurTable [Row, Col]:=-Self. CurTable [Row, Col];

End

Else {Якщо треба знайти мінімум:}

Begin{Множимо вільний член функції мети на -1:}

Self. CurTable [Row, CurWidth-1]:=-Self. CurTable [Row, CurWidth-1];

{Назва функції теж міняє знак:}

ChangeSignForValOrVarName (Self. CurHeadCol[Row]);

{Тепер це протилежна функція для максимізації:}

Self. CurHeadCol[Row].ElmType:=bc_DestFuncToMax;

End;

PrepareDFuncForSimplexMaximize:=True;

End;

Function TGridFormattingProcs. PrepareDestFuncInMultiDFuncLTask (

SFuncRowNum, MinDestFuncRowNum: Integer):Boolean;

{Готує таблицю для розв'язування задачі ЛП відносно одної заданої функції

мети із багатокритеріальної задачі.

Вхідні дані:

SFuncRowNum– номер рядка у таблиці Self. CopyTable (і комірки у

стовпці-заголовку Self. CopyHeadCol), в якому записана портібна

функція мети;

DestFuncMinRowNum– номер найвищого (з найменшим номером) рядка

функції мети. Усі функції мети мають бути зібрані внизу таблиці;

Self. CopyTable– таблиця коефіцієнтів та вільних членів;

Self. CopyHeadRow– рядок-заголовок зі змінними та одиницею-множником

стовпця вільних членів (має бути останнім);

Self. CopyHeadCol– стовпець-заголовок з іменами функцій-нерівностей,

нулями (заголовки рядків-рівнянь), іменами функцій мети

(що максимізуються (тип комірки bc_DestFuncToMax) або мінімізуються

(тип bc_DestFuncToMin)).

Вихідні дані:

Умова для одної функції:

Self. CurTable– таблиця коефіцієнтів та вільних членів з одною

функцією мети в останньому рядку, для максимізації симплекс-методом;

Self. CurHeadRow– рядок-заголовок;

Self. CurHeadCol– стовпець-заголовок з іменами функцій-нерівностей,

нулями (заголовки рядків-рівнянь), і одною коміркою функції мети

(остання, найнижча комірка), яку треба максимізувати. Якщо у цій

комірці перед назвою функції стоїть знак «–», то після максимізації

її треба замінити на протилежну функцію (і отримати мінімізацію

тої функції, яка була задана в умові).

Підпрограма повертає ознаку успішності підготовки умови із одною

заданою функцією мети.}

Var Row, Col, CurWidth, CurHeight: Integer;

Const sc_CurProcName='PrepareDestFuncInMultiDFuncLTask';

Label LStopLabel;

Begin

If Not (Self. GoToEnd) then

Begin{Демонструємо функцію мети у таблиці, з якою будемо працювати:}

{Таблиця багатокритеріальної задачі для відображення:}

Self. CurHeadRow:=Self. CopyHeadRow; Self. CurHeadCol:=Self. CopyHeadCol;

Self. CurTable:=Self. CopyTable;

{Координати рядка функції для помітки його кольором:}

Self. CurGridSolveCol:=Self.CHeadColNum;

Self. CurGridSolveRow:=SFuncRowNum+Self.CHeadRowNum+bc_LTaskRowsBeforeVars;

{Відображаємо і чекаємо реакції користувача:}

WaitForNewStep (Self.CHeadColNum, Self.CHeadRowNum);

If Self. Stop then Goto LStopLabel;

End;

CurWidth:=Length (Self. CopyHeadRow);

CurHeight:=Length (Self. CopyHeadCol);

If (SFuncRowNum<0) or (MinDestFuncRowNum<0) or

(SFuncRowNum>=CurHeight) or (MinDestFuncRowNum>=CurHeight) then

Begin

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add (sc_CurProcName+sc_RowNumsIsOutOfTable);

PrepareDestFuncInMultiDFuncLTask:=False; Exit;

End;

{Формуємо умову однокритеріальної задачі лінійного програмування із

копії умови багатокритеріальної задачі:}

{Копіюємо заголовки і таблицю коефіцієнтів:}

SetLength (Self. CurHeadRow, CurWidth); {довжина для рядка заголовка така сама}

For Col:=0 to CurWidth-1 do Self. CurHeadRow[Col]:=Self. CopyHeadRow[Col];

{Стовпець-заголовок і висота таблиці мають усі рядки умов (рівнянь

та нерівностей) і один рядок функції мети:}

SetLength (Self. CurHeadCol, MinDestFuncRowNum+1);

SetLength (Self. CurTable, MinDestFuncRowNum+1, CurWidth);

For Row:=0 to MinDestFuncRowNum-1 do {копіюємо рядки умов:}

Begin

Self. CurHeadCol[Row]:=Self. CopyHeadCol[Row];

For Col:=0 to CurWidth-1 do

Self. CurTable [Row, Col]:=Self. CopyTable [Row, Col];

End;

{В останній рядок таблиці однокритеріальної задачі копіюємо заданий

рядок функції мети із багатокритеріальної задачі:}

Row:=MinDestFuncRowNum; {номер останнього рядка у однокритеріальній задачі}

Self. CurHeadCol[Row]:=Self. CopyHeadCol[SFuncRowNum];

For Col:=0 to CurWidth-1 do

Self. CurTable [Row, Col]:=Self. CopyTable [SFuncRowNum, Col];

PrepareDestFuncInMultiDFuncLTask:=Self. PrepareDFuncForSimplexMaximize;

Exit;

LStopLabel:

PrepareDestFuncInMultiDFuncLTask:=False; Exit;

End;

Procedure TGridFormattingProcs. ShowLTaskResultCalc (DualTaskVals: Boolean);

{Процедура зчитує значення функції мети у таблиці розв'язаної

однокритеріальної задачі, і значення усіх змінних або функцій в цьому

розв'язку. Відображає значення цих змінних, функцій-нерівностей, і

функції мети в Self. CurOutConsole.

Вхідні дані:

DualTaskVals – вмикач режиму відображення значень двоїстої задачі:

читаються значення змінних і функцій двоїстої задачі. Їхні

значення розміщені не на місці стовпця вільних членів, а у рядку

коефіцієнтів функції мети (функції мети прямої задачі). Вони є

значеннями змінних чи функцій, імена яких у рядку-заголовку.

Змінні чи функції-нерівності двоїстої задачі з іменами у

стовпці-заголовку є рівними нулю.

Таблиця розв'язаної однокритеріальної (з одною функцією мети) задачі:

Self. CurTable– таблиця коефіцієнтів та вільних членів;

Self. CurHeadRow– рядок-заголовок з іменами змінних, іменами

функцій-нерівностей (що перейшли в рядок-заголовок) та

одиницею-множником стовпця вільних членів (має бути останнім);

Self. CurHeadCol– стовпець-заголовок з іменами функцій-нерівностей,

іменами змінних (виключених), іменем функції мети.}

Const DestFuncsTypes=[bc_DestFuncToMax, bc_DestFuncToMin];

Var st1: String; CurColNum, CurRowNum, LastColNum, LastRowNum: Integer;

Begin

If Self. CurOutConsole<>Nil then

Begin

LastColNum:=Length (Self. CurHeadRow) – 1;

LastRowNum:=Length (Self. CurHeadCol) – 1;

st1:=sc_ResultIs;

If DualTaskVals then

st1:=st1+sc_ForDualTask

Else st1:=st1+sc_ForDirectTask;

Self. CurOutConsole. Lines. Add(st1);

Self. CurOutConsole. Lines. Add (sc_InHeadRow);

{Показуємо значення змінних (або функцій) у рядку-заголовку:}

For CurColNum:=0 to LastColNum-1 do

Begin

st1:='';

If Self. CurHeadRow[CurColNum].ElmType=bc_Number then

st1:=st1+FloatToStr (Self. CurHeadRow[CurColNum].AsNumber)

Else st1:=st1+Self. CurHeadRow[CurColNum].AsVarName;

st1:=st1 + sc_Space+sc_Equal+sc_Space;

{Усі змінні прямої задачі (або функції) у рядку-заголовку в точці

задачі рівні нулю, а змінні двоїстої – у рядку коефіцієнтів функції

мети:}

If DualTaskVals then

st1:=st1+ FloatToStr (Self. CurTable [LastRowNum, CurColNum])

Else st1:=st1+'0';

st1:=st1+sc_KrKm;

Self. CurOutConsole. Lines. Add(st1);

End;

Self. CurOutConsole. Lines. Add (sc_InHeadCol);

For CurRowNum:=0 to LastRowNum do

Begin

st1:='';

If Self. CurHeadCol[CurRowNum].ElmType=bc_Number then

st1:=st1+FloatToStr (Self. CurHeadCol[CurRowNum].AsNumber)

Else st1:=st1+Self. CurHeadCol[CurRowNum].AsVarName;

st1:=st1 + sc_Space+sc_Equal+sc_Space;

{Усі змінні прямої задачі (або функції) у стовпці-заголовку в точці

задачі мають свої значення у стовпці вільних членів,

а змінні двоїстої – рівні нулю:}

If (Self. CurHeadCol[CurRowNum].ElmType in DestFuncsTypes) or

Not(DualTaskVals) then

st1:=st1+ FloatToStr (Self. CurTable [CurRowNum, LastColNum])

Else st1:=st1+'0';

If (Self. CurHeadCol[CurRowNum].ElmType in DestFuncsTypes) then

st1:=sc_ResFunc+sc_Space+st1;

If CurRowNum=LastRowNum then st1:=st1+sc_Spot

Else st1:=st1+sc_KrKm;

Self. CurOutConsole. Lines. Add(st1);

End;

End;

End;

Procedure TGridFormattingProcs. ReadCurFuncSolution (Var SDValVecs:TFloatMatrix;

Var SDDestFuncVals:TFloatArr; SVecRow: Integer;

ToReadFuncVals: Boolean; DualTaskVals: Boolean);

{Процедура зчитує значення функції мети у таблиці розв'язаної

однокритеріальної задачі, і значення усіх змінних або функцій в цьому

розв'язку.

Вхідні дані:

SVecRow– номер поточної функції мети (нумерація з нуля) у масивах

SDValVecs і SDDestFuncVals;

ToReadFuncVals– перемикач: якщо рівний False, то зчитуються значення

змінних (і значення функції мети); True– зчитуються значення

функцій-нерівностей (і значення функції мети);

DualTaskVals– вмикач режиму читання змінних двоїстої задачі:

читаються значення змінних і функцій двоїстої задачі. Їхні

значення розміщені не на місці стовпця вільних членів, а у рядку

коефіцієнтів функції мети (функції мети прямої задачі). Вони є

значеннями змінних чи функцій, імена яких у рядку-заголовку.

Змінні чи функції-нерівності двоїстої задачі з іменами у

стовпці-заголовку є рівними нулю.

Таблиця розв'язаної однокритеріальної (з одною функцією мети) задачі:

Self. CurTable– таблиця коефіцієнтів та вільних членів;

Self. CurHeadRow– рядок-заголовок з іменами змінних, іменами

функцій-нерівностей (що перейшли в рядок-заголовок) та

одиницею-множником стовпця вільних членів (має бути останнім);

Self. CurHeadCol– стовпець-заголовок з іменами функцій-нерівностей,

іменами змінних (виключених), іменем функції мети. Функція мети

має бути в останньому рядку, і бути одна;

SDValVecs– масив для запису векторів значень змінних;

SDDestFuncVals– масив для запису значень функцій мети