Смекни!
smekni.com

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

ToDelColIfZeroInHRow: Boolean=True):Boolean;

{Функція виконує Жорданове виключення для елемента матриці

SDMatrix з координатами (RozElmCol, RozElmRow). Окрім обробки матриці,

здійснюється заміна місцями елементів у рядку і стовпцю-заголовках

матриці (SDHeadRow, SDHeadCol).

Вхідні дані:

RozElmCol– номер стовпця матриці, у якому лежить розв'язувальний елемент.

нумерація з нуля;

RozElmRow– номер рядка матриці, у якому лежить розв'язувальний елемент.

нумерація з нуля.

Розв'язувальний елемент не повинен бути рівним нулю, інакше виконання

Жорданового виключення не можливе;

SDHeadRow, SDHeadCol– рядок і стовпець-заголовки матриці. Рядок-заголовок

SDHeadRow повинен мати не менше елементів, ніж є ширина матриці. Він

містить множники. Стовпець-заголовок SDHeadCol повинен бути не коротшим

за висоту матриці. Він містить праві частини рівнянь (чи нерівностей)

системи. Рівняння полягають у тому що значення елементів

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

рядка матриці і елементів рядка-заголовка. Елементи у цих заголовках

можуть бути числами або рядками-іменами змінних. Якщо довжина

рядка-заголовка менша за ширину або стовпця-заголовка менша за висоту

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

проігнорована;

SDMatrix– матриця, у якій виконується Жорданове виключення;

ToDoMGI– прапорець, що вмикає режим модифікованого Жорданового виключення

(при ToDoMGI=True здійснюється модифіковане, інакше – звичайне).

Модифіковане Жорданове виключення використовується для матриці, у якій

було змінено знак початкових елементів, і змінено знаки елементів-

множників у рядку-заголовку. Використовується для симплекс-методу.

ToDelColIfZeroInHRow– прапорець, що вмикає видалення стовпця матриці із

розв'язувальним елементом, якщо після здійснення жорданівського

виключення у рядок-заголовок зі стовпця-заголовка записується число нуль.

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

SDHeadRow, SDHeadCol– змінені рядок та стовпець-заголовки. У них

міняються місцями елементи, що стоять навпроти розв'язувального елемента

(у його стовпці (для заголовка-рядка) і рядку (для заголовка-стовпця).

У заголовку-рядку такий елемент після цього може бути видалений, якщо

він рівний нулю і ToDelColIfZeroInHRow=True.

Тобто Жорданове виключення змінює ролями ці елементи (виражає один

через інший у лінійних рівняннях чи нерівностях);

SDMatrix– матриця після виконання Жорданового виключення;

DColDeleted– ознака того, що при виконанні Жорданового виключення

був видалений розв'язувальний стовпець із матриці (у його комірці

у рядку-заголовку став був нуль).

Функція повертає ознаку успішності виконання Жорданового виключення.

}


Var CurRow, CurCol, RowCount, ColCount: Integer;

SafeHeadElm:TValOrName;

MultiplierIfMGI:TWorkFloat;

CurMessage: String;

Begin

{Визначаємо кількість рядків і стовпців, які можна обробити:}

RowCount:=Length(SDMatrix);

If RowCount<=0 then Begin GI:=False; Exit; End;

ColCount:=Length (SDMatrix[0]);

If Length(SDHeadCol)<RowCount then RowCount:=Length(SDHeadCol);

If Length(SDHeadRow)<ColCount then ColCount:=Length(SDHeadRow);

If (RowCount<=0) or (ColCount<=0) then Begin GI:=False; Exit; End;

{Перевіряємо наявність розв'язуючого елемента у матриці (за координатами):}

If (RozElmCol>(ColCount-1)) or (RozElmRow>(RowCount-1)) then

Begin

CurMessage:=sc_InvCoordsOfResolvingElm+': ['+IntToStr (RozElmCol+1)+';'+

IntToStr (RozElmRow+1)+']'+sc_CrLf+

sc_MatrixSize+': ['+IntToStr(ColCount)+';'+IntToStr(RowCount)+']';

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add(CurMessage);

MessageDlg (CurMessage, mtError, [mbOk], 0);

GI:=False; Exit;

End;

{Якщо розв'язуючий елемент рівний нулю, то виконати Жорданове виключення

неможливо:}

If SDMatrix [RozElmRow, RozElmCol]=0 then

Begin

CurMessage:=sc_ZeroResolvingElm+': ['+IntToStr (RozElmCol+1)+';'+

IntToStr (RozElmRow+1)+']='+FloatToStr (SDMatrix[RozElmRow, RozElmCol]);

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add(CurMessage);

MessageDlg (CurMessage, mtError, [mbOk], 0);

GI:=False; Exit;

End;

{Виконуємо Жорданове виключення у матриці:}

{Обробляємо усі елементи матриці, що не належать до рядка і стовпця

розв'язуючого елемента:}

For CurRow:=0 to RowCount-1 do

For CurCol:=0 to ColCount-1 do

If (CurRow<>RozElmRow) and (CurCol<>RozElmCol) then

Begin

SDMatrix [CurRow, CurCol]:=

(SDMatrix [CurRow, CurCol]*SDMatrix [RozElmRow, RozElmCol] –

SDMatrix [CurRow, RozElmCol]*SDMatrix [RozElmRow, CurCol]) /

SDMatrix [RozElmRow, RozElmCol];

End;

{+1, якщо задано зробити звичайне Жорданове виключення;

-1 – якщо задано модифіковане:}

MultiplierIfMGI:=(1–2*Abs (Ord(ToDoMGI)));

{Елементи стовпця розв'язуючого елемента (окрім його самого)

ділимо на розв'язуючий елемент:}

For CurRow:=0 to RowCount-1 do

If CurRow<>RozElmRow then

SDMatrix [CurRow, RozElmCol]:=MultiplierIfMGI*SDMatrix [CurRow, RozElmCol]/

SDMatrix [RozElmRow, RozElmCol];

{Елементи рядка розв'язуючого елемента (окрім його самого)

ділимо на розв'язуючий елемент з протилежним знаком:}

For CurCol:=0 to ColCount-1 do

If CurCol<>RozElmCol then

SDMatrix [RozElmRow, CurCol]:=-MultiplierIfMGI*SDMatrix [RozElmRow, CurCol]/

SDMatrix [RozElmRow, RozElmCol];

{Заміняємо розв'язуючий елемент на обернене до нього число:}

SDMatrix [RozElmRow, RozElmCol]:=1/SDMatrix [RozElmRow, RozElmCol];

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

стовпці і рядку розв'язуючого елемента:}

SafeHeadElm:= SDHeadRow[RozElmCol];

SDHeadRow[RozElmCol]:=SDHeadCol[RozElmRow];

SDHeadCol[RozElmRow]:=SafeHeadElm;

{Якщо виконуємо модиівковане Жорданове виключення, то змінюють

знаки і ці елементи, що помінялись місцями:}

If ToDoMGI then

Begin

ChangeSignForValOrVarName (SDHeadRow[RozElmCol]);

ChangeSignForValOrVarName (SDHeadCol[RozElmRow]);

End;

DColDeleted:=False;

{Якщо у рядку-заголовку навпроти розв'язуючого елемента опинився нуль,

і задано видаляти у такому випадку цей елемент разом із стовпцем

розв'язуючого елемента у матриці, то видаляємо:}

If ToDelColIfZeroInHRow and (SDHeadRow[RozElmCol].ElmType=bc_Number) then

If SDHeadRow[RozElmCol].AsNumber=0 then

Begin

DeleteFromArr (SDHeadRow, RozElmCol, 1);

DelColsFromMatr (SDMatrix, RozElmCol, 1);

DColDeleted:=True;

End;

GI:=True;

End;

Procedure ChangeRowsPlaces (Var SDMatr:TFloatMatrix; Row1, Row2: Integer);

overload;

Var SafeCurRow:TFloatArr;

Begin

SafeCurRow:=SDMatr[Row1];

SDMatr[Row1]:=SDMatr[Row2];

SDMatr[Row2]:=SafeCurRow;

End;

Procedure ChangeRowsPlaces (Var SDMatr:TFloatMatrix; Var SDHeadCol:TValOrNameMas;

Row1, Row2: Integer; ToChangeInitPosNums: Boolean=False); overload;

{Процедура міняє місцями рядки у таблиці зі стовпцем-заголовком.

Вхідні дані:

SDMatr– таблиця;

SDHeadCol– стовпець-заголовок таблиці;

Row1, Row2 – рядки, що треба поміняти місцями;

ToChangeInitPosNums– вмикач зміни номерів по порядку у

стовпці-заголовку. Якщо рівний True, то рядки, що помінялися місцями,

міняються також і позначками про номер по порядку та розміщення

як рядка чи стовпця (що присвоювалися їм при створенні).

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

SDMatr– таблиця;

SDHeadCol– стовпець-заголовок таблиці.}

Var SafeCurHeadCell:TValOrName;

Begin

SafeCurHeadCell:=SDHeadCol[Row1];

SDHeadCol[Row1]:=SDHeadCol[Row2];

SDHeadCol[Row2]:=SafeCurHeadCell;

If ToChangeInitPosNums then

Begin

SDHeadCol[Row2].VarInitPos:=SDHeadCol[Row1].VarInitPos;

SDHeadCol[Row2].VarInitInRow:=SDHeadCol[Row1].VarInitInRow;

SDHeadCol[Row1].VarInitPos:=SafeCurHeadCell. VarInitPos;

SDHeadCol[Row1].VarInitInRow:=SafeCurHeadCell. VarInitInRow;

End;

ChangeRowsPlaces (SDMatr, Row1, Row2);

End;

Procedure ChangePlaces (Var SDMas:TFloatArr; Elm1, Elm2: Integer);

Var SafeElm:TWorkFloat;

Begin

SafeElm:=SDMas[Elm1];

SDMas[Elm1]:=SDMas[Elm2];

SDMas[Elm2]:=SafeElm;

End;

Procedure ChangeColsPlaces (Var SDMatr:TFloatMatrix; Col1, Col2: Integer);

overload;

Var CurRow: Integer;

Begin

For CurRow:=0 to Length(SDMatr) – 1 do

ChangePlaces (SDMatr[CurRow], Col1, Col2);

End;

Procedure ChangeColsPlaces (Var SDMatr:TFloatMatrix; Var SDHeadRow:TValOrNameMas;

Col1, Col2: Integer; ToChangeInitPosNums: Boolean=False); overload;

{Процедура міняє місцями стовпці у таблиці з рядком-заголовком.

Вхідні дані:

SDMatr– таблиця;

SDHeadRow– рядок-заголовок таблиці;

Row1, Row2 – рядки, що треба поміняти місцями;

ToChangeInitPosNums– вмикач зміни номерів по порядку у

стовпці-заголовку. Якщо рівний True, то рядки, що помінялися місцями,

міняються також і позначками про номер по порядку та розміщення

як рядка чи стовпця (що присвоювалися їм при створенні).

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

SDMatr– таблиця;

SDHeadCol– рядок-заголовок таблиці.}

Var SafeCurHeadCell:TValOrName;

Begin

SafeCurHeadCell:=SDHeadRow[Col1];

SDHeadRow[Col1]:=SDHeadRow[Col2];

SDHeadRow[Col2]:=SafeCurHeadCell;

If ToChangeInitPosNums then

Begin

SDHeadRow[Col2].VarInitPos:=SDHeadRow[Col1].VarInitPos;

SDHeadRow[Col2].VarInitInRow:=SDHeadRow[Col1].VarInitInRow;

SDHeadRow[Col1].VarInitPos:=SafeCurHeadCell. VarInitPos;

SDHeadRow[Col1].VarInitInRow:=SafeCurHeadCell. VarInitInRow;

End;

ChangeColsPlaces (SDMatr, Col1, Col2);

End;

Procedure TGridFormattingProcs. WaitForNewStep (HeadColNum, HeadRowNum: Integer);

{Зупиняє хід вирішування, відображає поточний стан таблиці, і чекає,

доки не буде встановлений один з прапорців:

Self. Continue, Self. GoToEnd або Self. Stop.

Якщо прапорці Self. GoToEnd або Self. Stop вже були встановлені до

виклику цієї процедури, то процедура не чекає встановлення прапорців.}

Begin

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

Self. Continue=True, незважаючи на поточний стан цього прапорця:}

Self. Continue:=False;

{Відображаємо поточний стан таблиці, якщо не ввімкнено режим

роботи без зупинок:}

If Not (Self. GoToEnd) then

Self. WriteTableToGrid (HeadColNum, HeadRowNum, True);

{Чекаємо підтвердження для наступного кроку, або переривання

розв'язування:}

While Not (Self. Continue or Self. GoToEnd or Self. Stop) do

Application. ProcessMessages;

End;

Function TGridFormattingProcs. SearchNozeroSolveCell (CurRowNum,

CurColNum, MaxRow, MaxCol: Integer;

HeadRowNum, HeadColNum: Integer;

ToSearchInRightColsToo: Boolean=True):Boolean;

{Пошук ненульової розв'язувальної комірки для вирішування системи рівнянь

або при вирішуванні задачі максимізації/мінімізації лінійної форми

симплекс-методом (починаючи з комірки [CurRowNum, CurColNum]).}

Const sc_CurProcName='SearchNozeroSolveCell';

Var CurSearchRowNum, CurSearchColNum: Integer;

st1: String;

Begin

{Якщо комірка, що хотіли взяти розв'язувальною, рівна нулю:}

If Self. CurTable [CurRowNum, CurColNum]=0 then

Begin

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add (sc_CurProcName+sc_ZeroKoef+

' ['+IntToStr (CurColNum+1)+'; '+IntToStr (CurRowNum+1)+']'+