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– масив для запису значень функцій мети