Смекни!
smekni.com

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

Self. CurGridSolveCol:=0; Self. CurGridSolveRow:=0;

WaitForNewStep (HeadColNum, HeadRowNum); {відмічаємо новий крок}

If Self. Stop then Goto LStopLabel;

If Self. CurOutConsole<>Nil then

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

{############## Шукаємо опорний розв'язок задачі: ##############}

CurRowNum:=HiNoIndepRow;

While CurRowNum<=(Length (Self. CurHeadCol) – 2) do

Begin

{Якщо знайшли від'ємний елемент у стовпці вільних членів:}

If Self. CurTable [CurRowNum, Length (Self. CurHeadRow) – 1]<0 then

Begin

{Для помітки поточного рядка на екранній таблиці:}

Self. CurGridSolveCol:=HeadColNum;

Self. CurGridSolveRow:=CurRowNum+HeadRowNum+bc_LTaskRowsBeforeVars;

WaitForNewStep (HeadColNum, HeadRowNum);

If Self. Stop then Goto LStopLabel;

{Шукаємо у рядку перший від'ємний коефіцієнт:}

For CurColNum:=0 to Length (Self. CurHeadRow) – 2 do

If CurTable [CurRowNum, CurColNum]<0 then Break;

If CurColNum>(Length (Self. CurHeadRow) – 2) then {Якщо усі невід'ємні:}

Begin

{Якщо вільний член від'ємний, а коефіцієнти невід'ємні, то

система несумісна:}

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add (sc_CurProcName+sc_DoubleSpot+sc_Space+

sc_NoVals);

Self. WasNoRoots:=True;

Self. WriteTableToGrid (HeadColNum, HeadRowNum, True);

SolveLTaskToMax:=True; Exit;

End;

{Якщо від'ємний коефіцієнт у рядку обрано, шукаємо МНВ

(мінімальне невід'ємне серед відношень вільних членів до членів

стовпця, у якому обрали цей коефіцієнт):}

SearchMNNCellForCol (CurColNum, HiNoIndepRow, Length (Self. CurHeadCol) – 2,

CurRow2N, False);

If CurRow2N<0 then {Якщо МНВ не знайдено:}

Begin

Self. WriteTableToGrid (HeadColNum, HeadRowNum, True);

SolveLTaskToMax:=False; Exit;

End;

{Якщо МНВ знайдено:}

Self. CurGridSolveCol:=CurColNum + HeadColNum+bc_LTaskColsBeforeVars;

Self. CurGridSolveRow:=CurRow2N + HeadRowNum+bc_LTaskRowsBeforeVars;

WaitForNewStep (HeadColNum, HeadRowNum);

If Self. Stop then Goto LStopLabel;

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

If Not (Self.GI (CurColNum, CurRow2N, Self. CurHeadRow,

Self. CurHeadCol, Self. CurTable, ColDeleted, True,

True)) then

Begin

SolveLTaskToMax:=False; Exit;

End;

If CurRow2N<>CurRowNum then {Якщо виключили не цей рядок:}

System. Continue; {продовжуємо працювати з цим рядком}

End; {If Self. CurTable [CurRowNum, Length (Self. CurHeadRow) – 1]<0 then…}

Inc(CurRowNum);

End; {While CurRowNum<=(Length (Self. CurHeadCol) – 2) do…}

If Self. CurOutConsole<>Nil then

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

{Ховаємо розв'язувальну комірку у екранній таблиці:}

Self. CurGridSolveCol:=0; Self. CurGridSolveRow:=0;

WaitForNewStep (HeadColNum, HeadRowNum); {відмічаємо новий крок}

If Self. Stop then Goto LStopLabel;

If Self. CurOutConsole<>Nil then

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

{############## Шукаємо оптимальний розв'язок задачі: ##############}

CurColNum:=0;

While CurColNum<=(Length (Self. CurHeadRow) – 2) do

Begin

ColDeleted:=False;

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

If CurTable [Length(Self. CurHeadCol) – 1, CurColNum]<0 then

Begin

{Шукаємо МНВ (мінімальне невід'ємне серед відношень вільних членів

до членів стовпця, у якому обрали цей коефіцієнт) серед усіх рядків

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

SearchMNNCellForCol (CurColNum, HiNoIndepRow, Length (Self. CurHeadCol) – 2,

CurRow2N, False);

If CurRow2N<0 then {Якщо МНВ не знайдено:}

Begin{то функція мети не обмежена зверху, максимальне значення безмежне:}

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add (sc_CurProcName+sc_DoubleSpot+sc_Space+

sc_UnlimitedFunc);

Self. WasManyRoots:=True;

Self. WriteTableToGrid (HeadColNum, HeadRowNum, True);

SolveLTaskToMax:=True; Exit;

End;

{Якщо МНВ знайдено:}

Self. CurGridSolveCol:=CurColNum + HeadColNum+bc_LTaskColsBeforeVars;

Self. CurGridSolveRow:=CurRow2N + HeadRowNum+bc_LTaskRowsBeforeVars;

WaitForNewStep (HeadColNum, HeadRowNum);

If Self. Stop then Goto LStopLabel;

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

If Not (Self.GI (CurColNum, CurRow2N, Self. CurHeadRow,

Self. CurHeadCol, Self. CurTable, ColDeleted, True,

True)) then

Begin

SolveLTaskToMax:=False; Exit;

End;

CurColNum:=0; {після виключення могли з'явитися нові від'ємні комірки}

System. Continue;

End;

If Not(ColDeleted) then Inc(CurColNum);

End;

{Якщо назва функції мети вказана зі знаком «–», то це протилежна

функція мети. Змінимо знаки у її рядку, і отримаємо шукану

мінімізацію функції:}

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

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

Begin

ChangeSignsInRow(CurRowNum);

Self. CurHeadCol[CurRowNum].ElmType:=bc_DestFuncToMin;

End;

If Self. CurOutConsole<>Nil then

Self. CurOutConsole. Lines. Add (sc_CurProcName+sc_DoubleSpot+sc_Space+

sc_ValFound);

Self. ShowLTaskResultCalc(DualTaskVals);

Self. SolWasFound:=True;

SolveLTaskToMax:=True;

{Ховаємо розв'язувальну комірку у екранній таблиці:}

Self. CurGridSolveCol:=0; Self. CurGridSolveRow:=0;

WaitForNewStep (HeadColNum, HeadRowNum);

Exit;

LStopLabel:

If Self. CurOutConsole<>Nil then

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

Self. CurGridSolveCol:=0; Self. CurGridSolveRow:=0;

SolveLTaskToMax:=False;

Exit;

End;

procedure TGridFormattingProcs. EditLineEqsOnNewRow (Sender: TObject;

NewRows: array of Integer);

{Підтримує форматування стовпця нумерації таблиці у такому вигляді:

1

2

3

4

5

m}

Var CurNum: Integer; CurGrid:TStringGrid;

Begin

If Sender=Nil then Exit;

{Якщо до вмикання форматування був якийсь обробник події, запускаємо його:}

If @Self. OldOnNewRow<>Nil then Self. OldOnNewRow (Sender, NewRows);

If Sender is TStringGrid then

Begin

CurGrid:=TStringGrid(Sender);

For CurNum:=0 to Length(NewRows) – 1 do

Begin

{Нумерація з третього рядка, бо два перших – заголовки:}

If NewRows[CurNum]>=(Self.CHeadRowNum+1) then

Begin

CurGrid. Cells [0, NewRows[CurNum]]:=IntToStr (NewRows[CurNum]-

Self.CHeadRowNum);

End;

End;

End;

End;

procedure TGridFormattingProcs. EditLineEqsOnNewCol (Sender: TObject;

NewCols: array of Integer);

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

такому вигляді:

1 2 3 4 5… nn+1

x1 x2 x3 x4 x5… xn1

}

Var CurNum: Integer; CurGrid:TStringGrid;

CurColNumStr: String;

Begin

If Sender=Nil then Exit;

{Якщо до вмикання форматування був якийсь обробник події, запускаємо його:}

If @Self. OldOnNewCol<>Nil then Self. OldOnNewCol (Sender, NewCols);

If Sender is TStringGrid then

Begin

CurGrid:=TStringGrid(Sender);

For CurNum:=0 to Length(NewCols) – 1 do

Begin

{Заголовки лише для комірок, які можна редагувати:}

If NewCols[CurNum]>=(Self.CHeadColNum+1) then

Begin

CurColNumStr:=IntToStr (NewCols[CurNum] – Self.CHeadColNum);

CurGrid. Cells [NewCols[CurNum], 0]:=CurColNumStr;

{Останній стовпець – числа у правих частинах рівнянь:}

If (NewCols[CurNum]+1)=CurGrid. ColCount then

CurGrid. Cells [NewCols[CurNum], 1]:=sc_RightSideValsHdr

{в усіх інших – коефіцієнти при змінних X1…Xn:}

Else

CurGrid. Cells [NewCols[CurNum], 1]:=sc_XVarName+CurColNumStr;

End;

End;

If Length(NewCols)>0 then

Begin

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

в останному з них оновлюємо підпис: тепер він буде з іменем змінної

xn»), а не з іменем стовпця правих частин рівнянь (a).

(Тут покладаємося на те, що номери оновлених стовпців сортовані

за зростанням):}

If NewCols[0]>(Self.CHeadColNum+1) then

CurGrid. Cells [NewCols[0] – 1, 1]:=sc_XVarName+IntToStr (NewCols[0]-

(Self.CHeadColNum+1));

End

Else {Якщо нових стовпців немає (тобто кількість стовпців зменшилася):}

Begin {Оновлюємо підпис останнього стовпця (праві частини рівнянь):}

CurGrid. Cells [CurGrid. ColCount-1, 1]:=sc_RightSideValsHdr;

End;

End;

End;

procedure TGridFormattingProcs. EditLineEqsOnDrawCell (Sender: TObject; ACol,

ARow: Integer; Rect: TRect; State: TGridDrawState);

{Процедура виконується при малюванні кожної комірки StringGrid

у режимі набору вхідних даних системи лінійних рівнянь.

Зафарбовує в інший колір останній стовпець – стовпець

правих частин рівнянь.}

VarCurGrid:TStringGrid; SafeBrushColor:TColor;

Begin

If Sender=Nil then Exit;

{Якщо до вмикання форматування був якийсь обробник події, запускаємо його:}

If @Self. OldOnDrawCell<>Nil then Self. OldOnDrawCell (Sender, ACol, ARow, Rect,

State);

If Sender is TStringGrid then

Begin

CurGrid:=TStringGrid(Sender);

SafeBrushColor:=CurGrid. Canvas. Brush. Color;

{Комірки останнього стовпця є стовпцем правих сторін рівнянь.

Фарбуємо їх у блакитний колір (окрім комірок заголовка):}

If (ACol>=(CurGrid. ColCount-bc_LineEqM2ColsAfterVars)) and

(Not (gdFixed in State)) then

Begin

CurGrid. Canvas. Brush. Color:=lwc_RightSideColColor;

{Малюємо текст на фоні з кольором Brush:}

CurGrid. Canvas. TextRect (Rect, Rect. Left, Rect. Top,

CurGrid. Cells [ACol, ARow]);

End;

CurGrid. Canvas. Brush. Color:=SafeBrushColor;

End;

End;

procedure TGridFormattingProcs. SolveLineEqsM1OrM2OnDrawCell (Sender: TObject;

ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);

{Процедура фарбує комірки (їхній фон) таблиці вирішування системи лінійних

рівнянь у стовпці правих частин (вільних членів). У залежності від

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

(1-ий спосіб, з отриманням оберненої матриці коефіцієнтів), або останнім

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

стовпців цих нулів).}

Var CurGrid:TStringGrid; SafeBrushColor:TColor; CurColor:TColor;

Begin

If Sender=Nil then Exit;

{Якщо до вмикання форматування був якийсь обробник події, запускаємо його:}

If @Self. OldOnDrawCell<>Nil then Self. OldOnDrawCell (Sender, ACol, ARow, Rect,

State);

If Sender is TStringGrid then

Begin

CurGrid:=TStringGrid(Sender);

SafeBrushColor:=CurGrid. Canvas. Brush. Color;

CurColor:=bc_NotColored;

If Not (gdFixed in State) then {якщо комірка не у заголовках StringGrid}

Begin

{У режимі розв'язування способом 1 відмічаємо перший стовпець

кольором, а у режимі способу 2 – відмічаємо останній

(стовпець правих частин – вільних членів):}

If ((Self. CurFormatState=fs_SolvingEqsM1) and

(ACol<(Self.CHeadColNum+bc_LineEqM1ColsBeforeVars))) or

((Self. CurFormatState=fs_SolvingEqsM2) and

(ACol>=(CurGrid. ColCount-bc_LineEqM2ColsAfterVars))) then

CurColor:=lwc_RightSideColColor

{Якщо це комірка коефіцієнта при змінній, і задача у ході вирішування:}

Else if InSolving then

Begin

If Self. CurGridSolveCol=ACol then {якщо це розв'язувальний стовпець:}

Begin

If Self. CurGridSolveRow=ARow then {якщо це розв'язувальна комірка:}

CurColor:=lwc_SolveCellColor

Else CurColor:=lwc_SolveColColor;

End{Якщо це розв'язувальний рядок (але не розв'язувальна комірка):}

Else if Self. CurGridSolveRow=ARow then CurColor:=lwc_SolveRowColor;

End;

End;

If CurColor<>bc_NotColored then {якщо комірку треба пофарбувати:}

Begin {Малюємо текст на фоні з кольором CurColor:}

CurGrid. Canvas. Brush. Color:=CurColor;

CurGrid. Canvas. TextRect (Rect, Rect. Left, Rect. Top,

CurGrid. Cells [ACol, ARow]);

End;

CurGrid. Canvas. Brush. Color:=SafeBrushColor;

End;

End;

procedure TGridFormattingProcs. EdLineTaskOnNewRow (Sender: TObject;

NewRows: array of Integer);

{Процедура працює при виникненні події оновлення рядка чи додавання нового

рядка у GrowingStringGrid.

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

такому вигляді:

1 y1

2 y2

3 y3

4 y4

5 y5

mym

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

заповнюються значеннями типу «функції-нерівності»).}