Смекни!
smekni.com

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

}

Constsc_CurProcName='MakeDualLTask';

Var SafeMas:TValOrNameMas; CurCol, CurRow, DFuncCount: Integer;

DualTType:TDualTaskType; NewDFuncType, OldDFuncType:THeadLineElmType;

Begin

SafeMas:=Nil;

If Self. CurFormatState<>fs_EnteringLTask then

Begin

If Self. CurOutConsole<>Nil then

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

MakeDualLTask:=False; Exit;

End;

If Self. CurGridModified then

Begin

If Not (Self. GetTask(True)) then

Begin

MakeDualLTask:=False; Exit;

End;

End;

If Self. TaskHeight<=0 then {Якщо таблиця пуста:}

Begin

If Self. CurOutConsole<>Nil then

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

MakeDualLTask:=False; Exit;

End;

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

(для максимізації чи мінімізації):}

DFuncCount:=0; DualTType:=dt_MaxToMin; OldDFuncType:=bc_DestFuncToMax;

For CurRow:=0 to Length (Self. CurHeadCol) – 1 do

Begin

If Self. CurHeadCol[CurRow].ElmType=bc_DestFuncToMax then

Begin

DualTType:=dt_MaxToMin;

OldDFuncType:=Self. CurHeadCol[CurRow].ElmType;

Inc(DFuncCount);

End

Else if Self. CurHeadCol[CurRow].ElmType=bc_DestFuncToMin then

Begin

DualTType:=dt_MinToMax;

OldDFuncType:=Self. CurHeadCol[CurRow].ElmType;

Inc(DFuncCount);

End;

End;

{Якщо функцій мети декілька або жодної:}

If DFuncCount<>1 then

Begin

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add (sc_CurProcName+

sc_CanMakeDTaskOnlyForOneDFunc+IntToStr(DFuncCount));

MakeDualLTask:=False; Exit;

End;

If DualTType=dt_MaxToMin then NewDFuncType:=bc_DestFuncToMin

Else NewDFuncType:=bc_DestFuncToMax;

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

рядків залишаємо на тих самих місцях (і присвоюємо тим рядкам, які

стають на ці місця):}

Self. ShiftRowsDown([bc_DestFuncToMax, bc_DestFuncToMin], True);

Transpose (Self. CurTable); {транспонуємо таблицю коефіцієнтів}

{Обробляємо заголовки таблиці у відповідність до двоїстої задачі:}

{Для рядка-заголовка, що стане стовпцем-заголовком:}

For CurCol:=0 to Length (Self. CurHeadRow) – 1 do

Begin {Проходимо по усіх змінних і останньому елементу –

множнику стовпця вільних членів – одиниці:}

If Self. CurHeadRow[CurCol].ElmType=bc_DependentVar then {Якщо змінна >=0:}

Begin {Ця комірка буде заголовком функції умови-нерівності зі знаком «>=»:}

Self. CurHeadRow[CurCol].ElmType:=bc_FuncVal;

Self. CurHeadRow[CurCol].VarInitInRow:=False;

{Формуємо назву функції:}

{якщо змінна має назву змінної двоїстої задачі, то дамо назву

функції прямої задачі, якщо назва прямої – назву двоїстої:}

If Pos (sc_DualTaskVarNameStart, Self. CurHeadRow[CurCol].AsVarName)>0 then

Self. CurHeadRow[CurCol].AsVarName:=sc_YFuncName + IntToStr (CurCol+1)

Else Self. CurHeadRow[CurCol].AsVarName:=sc_DualTaskFuncNameStart +

IntToStr (CurCol+1);

{Якщо переходимо від задачі максимізації до двоїстої задачі

мінімізації, то для нерівності треба буде змінити знак «>=» на «<=»,

(якщо для змінної була умова «>=0», і заголовок для неї був додатний),

тому змінюємо знак заголовка:}

IfDualTType=dt_MaxToMinthen

ChangeSignForValOrVarName (Self. CurHeadRow[CurCol]);

End {Якщо змінна вільна:}

Else if Self. CurHeadRow[CurCol].ElmType=bc_IndependentVar then

Begin{Ця комірка буде заголовком умови-рівняння:}

Self. CurHeadRow[CurCol].ElmType:=bc_Number;

Self. CurHeadRow[CurCol].AsNumber:=0;

End {Якщо це число:}

Else if Self. CurHeadRow[CurCol].ElmType=bc_Number then

Begin

If Self. CurHeadRow[CurCol].AsNumber=1 then {якщо це множник вільних членів}

Begin

Self. CurHeadRow[CurCol].ElmType:=NewDFuncType;

Self. CurHeadRow[CurCol].VarInitInRow:=False;

{Формуємо назву функції мети двоїстої задачі

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

If Pos (sc_DualDestFuncHdr,

Self. CurHeadCol [Length(Self. CurHeadCol) – 1].AsVarName)>0 then

Self. CurHeadRow[CurCol].AsVarName:=sc_DestFuncHdr

Else Self. CurHeadRow[CurCol].AsVarName:=sc_DualDestFuncHdr;

End;

End;

End;


{Для стовпця-заголовка, що стане рядком-заголовком:}

For CurRow:=0 to Length (Self. CurHeadCol) – 1 do

Begin

{Проходимо по усіх елементах-заголовках рядків, і останньому елементу –

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

IfSelf. CurHeadCol[CurRow].ElmType=bc_FuncValthen{Якщо нерівність «<=»:}

Begin

Self. CurHeadCol[CurRow].ElmType:=bc_DependentVar; {буде змінна >=0}

Self. CurHeadCol[CurRow].VarInitInRow:=True;

{Формуємо назву змінної:

якщо функція-нерівність має назву функції двоїстої задачі, то

дамо назву змінної прямої задачі, якщо назва прямої – назву двоїстої:}

If Pos (sc_DualTaskFuncNameStart, CurHeadCol[CurRow].AsVarName)>0 then

Self. CurHeadCol[CurRow].AsVarName:=sc_XVarName + IntToStr (CurRow+1)

Else Self. CurHeadCol[CurRow].AsVarName:=sc_DualTaskVarNameStart +

IntToStr (CurRow+1);

{Якщо переходимо від задачі мінімізації до двоїстої задачі

максимізації, то для змінної треба буде змінити знак і умову «<=0»

на «>=0», (якщо для нерівність була зі знаком «<=», і заголовок для

неї був додатний), тому змінюємо знак заголовка:}

If DualTType=dt_MinToMax then

ChangeSignForValOrVarName (Self. CurHeadCol[CurRow]);

End

Else if Self. CurHeadCol[CurRow].ElmType=bc_Number then

Begin

If Self. CurHeadCol[CurRow].AsNumber=0 then {Якщо 0, заголовок рівняння:}

Begin

Self. CurHeadCol[CurRow].ElmType:=bc_IndependentVar;

Self. CurHeadCol[CurRow].VarInitInRow:=True;

{Формуємо назву змінної двоїстої задачі

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

If Pos (sc_DualDestFuncHdr,

Self. CurHeadCol [Length(Self. CurHeadCol) – 1].AsVarName)>0 then

Self. CurHeadCol[CurRow].AsVarName:=sc_XVarName+IntToStr (CurRow+1)

Else Self. CurHeadCol[CurRow].AsVarName:=sc_DualTaskVarNameStart+

IntToStr (CurRow+1);

End;

End {Якщо заголовок рядка функції мети:}

Else if Self. CurHeadCol[CurRow].ElmType=OldDFuncType then

Begin

Self. CurHeadCol[CurRow].ElmType:=bc_Number;

Self. CurHeadCol[CurRow].AsNumber:=1; {буде множник стовпця вільних членів}

End;

End;

{Міняємо рядок і стовпець-заголовки таблиці місцями:}

SafeMas:=Self. CurHeadRow;

Self. CurHeadRow:=Self. CurHeadCol;

Self. CurHeadCol:=SafeMas;

{У новому стовпці-заголовку шукаємо комірки-заголовки нерівностей «>=».

Їх заміняємо на «<=» множенням рядка на -1:}

For CurRow:=0 to Length (Self. CurHeadCol) – 1 do

Begin

If Self. CurHeadCol[CurRow].ElmType=bc_FuncVal then

Begin

If ValSign (Self. CurHeadCol[CurRow])=bc_Negative then

Self. ChangeSignsInRow(CurRow);

End;

End;

{У новому рядку-заголовку шукаємо комірки-заголовки залежних змінних,

які мають умову «<=0». Змінюємо цю умову на «>=0» множенням стовпця на -1:}

For CurCol:=0 to Length (Self. CurHeadRow) – 1 do

Begin

If Self. CurHeadRow[CurCol].ElmType=bc_DependentVar then

Begin

If ValSign (Self. CurHeadRow[CurCol])=bc_Negative then

Self. ChangeSignsInCol(CurCol);

End;

End;

{Відображаємо отриману таблицю у екранній таблиці:}

Self. WriteTableToGrid (Self.CHeadColNum, Self.CHeadRowNum);


MakeDualLTask:=True;

End;

Function TGridFormattingProcs. PrepareToSolveEqsWithM1: Boolean;

Const sc_CurProcName='PrepareToSolveEqsWithM1';

Var CurRow, ColToDel: Integer;

Begin

If (Self. CurFormatState=fs_EnteringEqs) or

(Self. CurFormatState=fs_NoFormatting) then

Begin

{Якщо таблиця не зчитана, то читаємо:}

If (Self. CurGridModified) and (Self. CurFormatState=fs_EnteringEqs) then

Begin

If Not (Self. GetTask) then

Begin

PrepareToSolveEqsWithM1:=False; Exit;

End;

End;

If Self. TaskHeight<=0 then {Якщо таблиця пуста:}

Begin

If Self. CurOutConsole<>Nil then

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

PrepareToSolveEqsWithM1:=False;

Exit;

End;

If Not (Self. EqM1TaskPrepared) then

Begin

{Копіюємо стовпець вільних членів (правих частин рівнянь) із

останнього стовпця таблиці до стовпця-заголовка:}

For CurRow:=0 to Length (Self. CurHeadCol) – 1 do

Begin

Self. CurHeadCol[CurRow].ElmType:=bc_Number;

Self. CurHeadCol[CurRow].AsNumber:=

Self. CurTable [CurRow, Length (CurTable[CurRow]) – 1];

End;

{Видаляємо цей останній стовпець із таблиці:}

ColToDel:=Length (Self. CurTable[0]) – 1;

DelColsFromMatr (Self. CurTable, ColToDel, 1);

DeleteFromArr (Self. CurHeadRow, ColToDel, 1);

End;

{Позиціювання відображення таблиці у даному режимі вирішування:}

Self.CHeadColNum:=CurGrid. FixedCols;

Self.CHeadRowNum:=CurGrid. FixedRows-1;

{Відображаємо таблицю, що підготована для розв'язування:}

Self. WriteTableToGrid (Self.CHeadColNum, Self.CHeadRowNum);

{Якщо таблиця пуста після перенесення останнього стовпця у

стовпець-заголовок:}

If Self. TaskHeight<=0 then

Begin

PrepareToSolveEqsWithM1:=False;

Exit;

End;

Self. EqM1TaskPrepared:=True;

PrepareToSolveEqsWithM1:=True;

End

Else

Begin

If Self. CurOutConsole<>Nil then

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

PrepareToSolveEqsWithM1:=False;

End;

End;

Function TGridFormattingProcs. PrepareToSolveEqsWithM2: Boolean;

Const sc_CurProcName='PrepareToSolveEqsWithM2';

Var CurRow: Integer;

Begin

If (Self. CurFormatState=fs_EnteringEqs) or

(Self. CurFormatState=fs_NoFormatting) then

Begin {Якщо таблиця не зчитана, то читаємо:}

If (Self. CurGridModified) and (Self. CurFormatState=fs_EnteringEqs) then

Begin

If Not (Self. GetTask) then

Begin

PrepareToSolveEqsWithM2:=False; Exit;

End;

End;

If Self. TaskHeight<=0 then {Якщо таблиця пуста:}

Begin

If Self. CurOutConsole<>Nil then

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

PrepareToSolveEqsWithM2:=False; Exit;

End;

If Not (Self. EqM2TaskPrepared) then

Begin

For CurRow:=0 to Length (Self. CurHeadCol) – 1 do

Begin

{Заповнюємо стовпець-заголовок нулями:}

Self. CurHeadCol[CurRow].ElmType:=bc_Number;

Self. CurHeadCol[CurRow].AsNumber:=0;

{Змінюємо знаки у останньому стовпці таблиці – стовпці вільних

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

таблиці коефіцієнтів лівих частин, повинні бути з протилежними

знаками:}

Self. CurTable [CurRow, Length (CurTable[CurRow]) – 1]:=

– Self. CurTable [CurRow, Length (CurTable[CurRow]) – 1];

End;

End;

{Позиціювання відображення таблиці у даному режимі вирішування:}

Self.CHeadColNum:=CurGrid. FixedCols;

Self.CHeadRowNum:=CurGrid. FixedRows-1;

{Відображаємо таюдицю, що підготована для розв'язування:}

Self. WriteTableToGrid (Self.CHeadColNum, Self.CHeadRowNum);

Self. EqM2TaskPrepared:=True;

PrepareToSolveEqsWithM2:=True;

End

Else

Begin

If Self. CurOutConsole<>Nil then

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

PrepareToSolveEqsWithM2:=False;

End;

End;

{TTableFormatState=(fs_EnteringEqs, fs_EnteringLTask, fs_SolvingEqsM1,

fs_SolvingEqsM2, fs_SolvingLTask,

fs_NoFormatting, fs_FreeEdit);}

Function TGridFormattingProcs. PrepareToSolveLTask: Boolean;

Const sc_CurProcName='PrepareToSolveLTask';

Begin

If (Self. CurFormatState=fs_EnteringLTask) or

(Self. CurFormatState=fs_NoFormatting) then

Begin {Якщо таблиця у режимі редагування задачі, і модифікована, то зчитуємо:}

If (Self. CurGridModified) and (Self. CurFormatState=fs_EnteringLTask) then

Begin

If Not (Self. GetTask) then {зчитуємо таблицю (умову) з екранної таблиці}

Begin

PrepareToSolveLTask:=False; Exit;

End;

End;

If Self. TaskHeight<=0 then {Якщо таблиця пуста:}

Begin

If Self. CurOutConsole<>Nil then

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

PrepareToSolveLTask:=False; Exit;

End;

If Not (Self.LTaskPrepared) then {якщо ця підготовка ще не виконувалася:}

Begin

{Зсуваємо рядки цільових функцій вниз. При цьому позначки порядку

рядків залишаємо на тих самих місцях (і присвоюємо тим рядкам, які

стають на ці місця):}

Self. ShiftRowsDown([bc_DestFuncToMax, bc_DestFuncToMin], True);

{Позиціювання відображення таблиці у даному режимі вирішування:}

Self.CHeadColNum:=CurGrid. FixedCols;

Self.CHeadRowNum:=CurGrid. FixedRows-1;

{Відображаємо таблицю, що підготована для розв'язування:}

Self. WriteTableToGrid (Self.CHeadColNum, Self.CHeadRowNum);

Self.LTaskPrepared:=True;

End;

PrepareToSolveLTask:=True;

End

Else

Begin

If Self. CurOutConsole<>Nil then

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

PrepareToSolveLTask:=False;

End;

End;

Function TGridFormattingProcs. PrepareDFuncForSimplexMaximize: Boolean;