26.      Васильев Ф.П. Методы решения экстремальных задач. М: Наука, 1980.-518с.


Вспомогательные указатели

Перечень сокращений

ЗВ - загрязняющее (вредное) вещество

ИЗА - источник загрязнения атмосферы

ПДВ - предельно допустимый выброс (допустимый выброс)

СЗЗ - санитарно-защитная зона

ПДКр - максимальная разовая предельно допустимая концентрация загрязняющего вещества в атмосферном воздухе населенных мест

ПДКс - среднесуточная предельно допустимая концентрация загрязняющего вещества в атмосферном воздухе населенных мест

ОБУВ - ориентировочный безопасный уровень воздействия загрязняющих веществ в атмосферном воздухе населенных мест

ГВС - газовоздушная смесь

ГОУ - газоочистная установка

ОНД - общесоюзный нормативный документ

НМУ - неблагоприятные метеорологические условия

УПРЗА - унифицированная программа расчета загрязнения атмосферы


Приложения

Unit1.pas

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, ShellAPI, ShlObj, StdCtrls, Buttons, CheckLst,Masks,inifiles,

 ComCtrls,simplex, Menus;

const MyDecimalSeparator='.';

type

 tsArray = array of string;

 tExtArrayx2 = array of tExtArray;

 TForm1 = class(TForm)

 Edit1: TEdit;

 GroupBox1: TGroupBox;

 CheckListBox1: TCheckListBox;

 Label1: TLabel;

 BitBtn1: TBitBtn;

 Button3: TButton;

 Memo1: TMemo;

 SpeedButton1: TSpeedButton;

 CheckBox1: TCheckBox;

 SpeedButton2: TSpeedButton;

 SpeedButton3: TSpeedButton;

 SpeedButton4: TSpeedButton;

 procedure FormCreate(Sender: TObject);

 procedure FormActivate(Sender: TObject);

 procedure BitBtn1Click(Sender: TObject);

 procedure Button3Click(Sender: TObject);

 procedure N2Click(Sender: TObject);

 procedure SpeedButton1Click(Sender: TObject);

 procedure SpeedButton2Click(Sender: TObject);

 procedure SpeedButton3Click(Sender: TObject);

 procedure SpeedButton4Click(Sender: TObject);

 private

 { Private declarations }

 public

 { Public declarations }

 end;

var

 Form1: TForm1;

 dir_path:string;

 IniFile: TIniFile;

implementation

{$R *.dfm}

//запись в ini файл

procedure SaveIni(s:string);

var

 IniPath: string;

 FileName: string;

begin

 GetDir(0,IniPath);

 FileName:=IniPath+'\sav.ini';

 IniFile:=TIniFile.Create(FileName);

 Inifile.WriteString('patch','dir',s);

 IniFile.Free;

end;

//чтение ini файла

function ReadIni:string;

var

 IniPath: string;

 FileName: string;

 s:string;

begin

 GetDir(0,IniPath);

 FileName:=IniPath+'\sav.ini';

 IniFile:=TIniFile.Create(FileName);

 ReadIni:=Inifile.ReadString('patch','dir',s);

 IniFile.Free;

end;

//--------- Удаляет пробел или запятую с краёв строки --------------------------

Function DelSpaceAndCap(s:string):string;

begin

 while pos(copy(s,1,1),' ')<>0 do delete(s,1,1);

 while pos(copy(s,length(s),1),' ')<>0 do delete(s,length(s),1);

 result:=s;

end;

//--------- вырезает из строки имя ---------------------------------------------

Function ReturnSubString(Var s:string):string;

var

 position,i : integer;

begin

 s:=DelSpaceAndCap(s);

 position:=0;

 for i:=1 to length(s)-1 do

 if (pos(copy(s,i,1),' ')<>0) and (position=0) then

 position:=i;

 if position=0 then begin

 result:=s;

 s:='';

 end else begin

 result := DelSpaceAndCap(copy(s,1,position));

 Delete(s,1,position);

 s:=DelSpaceAndCap(s);

 end;

end;

//вывод ограничений

//==============================================================================

procedure vv(a:real;mas:tExtArray; Sign: TOperation);

var

 i:integer;

 s,s2,s3:string;

begin

 s:=floattostr(mas[0]);

 for i:=1 to length(mas)-1 do

 s:=s+'+'+floattostr(mas[i]);

 if Sign=less then s2:=' < ';

 if Sign=Greater then s2:=' > ';

 if Sign=Equal then s2:=' = ';

 form1.memo1.lines.Add(s+s2+floattostr(a));

end;

//==============================================================================

//==============================================================================

//замена в строке всех вхождений одной подстроки на другую

function StrReplace(Str, Str1, Str2 : string):string;

 var

 p, L : integer;

 s:string;

begin

 s:=str;

 L:=length(str1);

 repeat

 p:=pos(str1, s);

 if p>0 then begin

 Delete(s,p,L);

 insert(str2, s, P);

 end;

 until P = 0;

 StrReplace:=s;

end;

//==============================================================================

//==============================================================================

//========================= считывание таблиц влияния таблиц источников на точки

procedure get_pointfunnel(s:string;countPoint:integer;countfunnel:integer;funnel_name:tsArray;funnel_m:tExtArray;

 var pointfunnelx2:tExtArrayx2; var point_cf:tExtArray);

var

 h:textfile;

 k,m:integer;

 s_temp,s_temp2,s_temp3:string;

 flag:boolean;

begin

 SetLength(PointFunnelx2,countPoint,countFunnel);

 SetLength(point_cf,countPoint);

 for k:=0 to countPoint-1 do begin

 point_cf[k]:=0;

 for m:=0 to countFunnel-1 do

 PointFunnelx2[k,m]:=0;

 end;

 AssignFile(h,dir_path+'\RESULT\'+'10pd'+s+'.ppp');

 reset(h);

 for k:=1 to 22 do readln(h,s_temp);

 s_temp:=StrReplace(s_temp,'|',' ');

 s_temp2:=s_temp;

 for m:= 0 to CountPoint-1 do begin //общий цикл

 flag:=true;

 while flag do begin

 if ReturnSubString(s_temp2)='Фоновая' then begin

 point_cf[m]:=strtofloat(copy(s_temp,pos('%',s_temp)-4,4));

 end else begin

 s_temp3:=ReturnSubString(s_temp);

 s_temp3:=ReturnSubString(s_temp);

 s_temp3:=ReturnSubString(s_temp);

 for k:=1 to 6 do s_temp2:=ReturnSubString(s_temp);

 //showmessage(s_temp2);

 for k:=0 to countFunnel-1 do

 if s_temp3=copy(funnel_name[k],8,4) then

 PointFunnelx2[m,k]:=strtofloat(s_temp2);//*funnel_m[k];

 end;

 readln(h,s_temp);

 s_temp:=StrReplace(s_temp,'|',' ');

 s_temp2:=s_temp;

 if ReturnSubString(s_temp2)='В' then flag:=false;

 end;

 for k:=1 to 16 do readln(h,s_temp);

 s_temp:=StrReplace(s_temp,'|',' ');

 s_temp2:=s_temp;

 end;

 closefile(h);

end;

//==============================================================================

//==============================================================================

//========================================================= получение источников

procedure get_funnel(s:string; var countFunnel:integer;var funnel_name:tsArray;

 var funnel_m:tExtArray;var funnel_min:tExtArray);

var

 h,h2 : textfile;

 index_funnel : integer;

 i,j : integer;

 s_temp,s_temp2:string;

begin

 AssignFile(h,dir_path+'\DAT\'+'ist_'+s+'.txt');

 reset(h);

 index_funnel:=-11;

 while s_temp<>'endI' do begin //чтение файла (установка размера массива)

 readln(h,s_temp);

 inc(index_funnel);

 end;

 closefile(h);

 CountFunnel:=index_funnel;

 setLength(funnel_m,CountFunnel);

 setLength(funnel_min,CountFunnel);

 setLength(funnel_name,CountFunnel);

 for i:=0 to countFunnel-1 do begin

 funnel_m[i]:=0;

 funnel_min[i]:=0;

 funnel_name[i]:='';

 end;

 AssignFile(h2,dir_path+'\DAT\'+'ist_'+s+'.txt');

 reset(h2);

 for j:=1 to 9 do

 readln(h2,s_temp);

 for i:= 0 to CountFunnel-1 do begin

 readln(h2,s_temp);

 funnel_name[i]:=ReturnSubString(s_temp);

 for j:=1 to 14 do

 s_temp2:=ReturnSubString(s_temp);

 funnel_m[i]:=strtofloat(ReturnSubString(s_temp));

 if DelSpaceAndCap(s_temp)<>'' then

 funnel_min[i]:=strtofloat(DelSpaceAndCap(s_temp))

 else funnel_min[i]:=0;

 end;

closefile(h2);

end;

//==============================================================================

//==============================================================================

//============================================================= получение точек

procedure get_point (s:string;var countPoint:integer;var point_pdk:tExtArray);

var

 index_point : integer;

 i,j : integer;

 h,h2 : textfile;

 s_temp : string;

begin

 index_point:=-2; // переменная для подсчета кол-ва точек

 AssignFile(h,dir_path+'\WORK\'+'htop'+s+'.ppp');

 reset(h);

 while s_temp<>'000' do begin//чтение файла (установка размера массива)

 readln(h,s_temp);

 inc(index_point);

 end;

 closefile(h);

 CountPoint:=index_point;

 setLength(point_pdk,countPoint);

 for i:=0 to countPoint-1 do

 point_pdk[i]:=0; //зануление

 AssignFile(h2,dir_path+'\WORK\'+'htop'+s+'.ppp');

 reset(h2);

 readln(h2,s_temp);

 for i:= 0 to countPoint-1 do begin

 readln(h2,s_temp);

 for j:=1 to 8 do

 point_pdk[i]:=strtofloat(ReturnSubString(s_temp));

 end;

closefile(h2);

end;

//==============================================================================

//==============================================================================

//=========================================== решение при помощи симплекс метода

procedure get_simplexsolve(countPoint:integer;countFunnel:integer;point_pdk:tExtArray;

 point_cf:tExtArray;funnel_m:tExtArray;funnel_min:tExtArray;

 pointfunnelx2:tExtArrayx2;var x:tExtArray;var s_temp:string);

var

 mas_temp : tExtArrayx2;

 i,j : integer;

 sim : TSimplex;

 L : tExtArray;

begin

setLength(mas_temp,countFunnel,countFunnel);

setLength(L,countFunnel);

setLength(x,countFunnel);

for i:=0 to countFunnel-1 do

 for j:=0 to countFunnel-1 do begin

 if i=j then mas_temp[i,j]:=1 else mas_temp[i,j]:=0;

 L[j]:=1;

 end;

Sim:=TSimplex.Create(L,true);

for i:=0 to countPoint-1 do begin

 //showmessage(vv(point_pdk[i],pointfunnelx2[i]));

 Sim.AddCons(point_pdk[i],pointfunnelx2[i],less);

 if form1.CheckBox1.Checked then vv(point_pdk[i],pointfunnelx2[i],less);

end;

for i:=0 to countFunnel-1 do begin

 Sim.AddCons(funnel_m[i],mas_temp[i],less);

 if funnel_min[i]>0 then begin

 Sim.AddCons(funnel_min[i],mas_temp[i],Greater);

 if form1.CheckBox1.Checked then vv(funnel_min[i],mas_temp[i],Greater);

 end;

end;

 if (Sim.Solve=SIMPLEX_DONE) then begin

 s_temp:='решение найдено';

 x:=Sim.GetSolution;

 end

 else s_temp:='Решения не существует';

end;

//==============================================================================

//==============================================================================

//==================================================== общий модуль для подсчета

procedure TForm1.Button3Click(Sender: TObject);

var

 s,s_temp,ss : string;

 countPoint : integer;

 countfunnel : integer;

 point_pdk : tExtArray;

 point_cf : tExtArray;

 funnel_m : tExtArray;

 funnel_min : tExtArray;

 funnel_name : tsArray;

 pointfunnelx2 : tExtArrayx2;

 i,j : integer;

 x : tExtArray;

 empty : boolean;

 h : textfile;

 funnelSumM,sumX:real;

begin

 funnelSumM:=0;

 sumX:=0;

 memo1.Clear;

 for i:=0 to checkListBox1.Items.Count-1 do begin

 if CheckListBox1.Checked[i] then begin

 application.ProcessMessages;

 s:=checklistbox1.Items.Strings[i];

 s:=returnSubString(s);

 application.ProcessMessages;

 get_point (s,countPoint,point_pdk);

 get_funnel(s,countFunnel,funnel_name,funnel_m,funnel_min);

 get_pointfunnel(s,countPoint,countfunnel,funnel_name,funnel_m,pointfunnelx2,point_cf);

 get_simplexsolve(countPoint,CountFunnel,point_pdk,point_cf,funnel_m,funnel_min,pointfunnelx2,x,s_temp);

 AssignFile(h,dir_path+'\RESULT\'+'h_pd'+s+'.gpv');

 rewrite(h);

 if s_temp='решение найдено' then begin

 memo1.lines.Add('');

 memo1.lines.Add(' Результаты расчета ПДВ (симплекс метод):');

 memo1.lines.Add(' ПРИМЕСЬ='+s);

 memo1.lines.Add('');

 memo1.lines.Add('---------------------------------------------------------');

 memo1.lines.Add('| Код |Существую-|Минимально| Расчетное | коэфф. |');

 memo1.lines.Add('| источника |щий выброс|возможный | значение | норми- |');

 memo1.lines.Add('| выброса | г/с | выброс | П Д В | рования |');

 memo1.lines.Add('|-----------|----------|---г/с----|----г/с----|---------|');

 writeln(h,'');

 writeln(h,' Результаты расчета ПДВ (симплекс метод):');

 writeln(h,' ПРИМЕСЬ='+s);

 writeln(h,'');

 writeln(h,'---------------------------------------------------------');

 writeln(h,'| Код |Существую-|Минимально| Расчетное | коэфф. |');

 writeln(h,'| источника |щий выброс|возможный | значение | норми- |');

 writeln(h,'| выброса | г/с | выброс | П Д В | рования |');

 writeln(h,'|-----------|----------|---г/с----|----г/с----|---------|');

 empty:=true;

 for j:=0 to countFunnel-1 do begin

 funnelSumM:=FunnelSumM+funnel_m[j];

 sumX:=SumX+x[j];

 if abs(x[j]-funnel_m[j])>0.0000001 then

 begin

 ss:='|'+funnel_name[j]+'| '+FloatToStrF(funnel_m[j],ffFixed,1000,6)+' | '+FloatToStrF(funnel_min[j],ffFixed,1000,6);

 ss:=ss+' | '+FloatToStrF(x[j],ffFixed,1000,7)+' | '+FloatToStrF(x[j]/funnel_m[j],ffFixed,1000,5)+' |';

 memo1.lines.Add(ss);

 writeln(h,ss);

 empty:=false;

 end;

 end;

 ss:='| в сумме: '+FloatToStrF(funnelSumM,ffFixed,1000,6)+' ';

 ss:=ss+FloatToStrF(sumX,ffFixed,1000,6)+' | '+ FloatToStrF(sumX/funnelSumM,ffFixed,1000,5)+' |';

 if empty then begin

 memo1.lines.Add('| Нет выбросов для снижения |');

 writeln(h,'| Нет выбросов для снижения |');

 end;

 if not empty then begin

 memo1.lines.Add('- - - - - - - - - - - - - - - - - - - - - - - - - - - - -');

 memo1.lines.Add(ss);

 writeln(h,'- - - - - - - - - - - - - - - - - - - - - - - - - - - - -');

 writeln(h,ss);

 end;

 memo1.lines.Add('---------------------------------------------------------');

 memo1.lines.Add('');

 memo1.lines.Add('');

 writeln(h,'---------------------------------------------------------');

 writeln(h,'');

 writeln(h,'');

 end else begin

 memo1.lines.Add('');

 memo1.lines.Add(' Результаты расчета ПДВ (симплекс метод):');

 memo1.lines.Add(' ПРИМЕСЬ='+s);

 memo1.lines.Add('');

 memo1.lines.Add('---------------------------------------------------------');

 memo1.lines.Add('| Решение не найдено |');

 memo1.lines.Add('---------------------------------------------------------');

 writeln(h,'');

 writeln(h,' Результаты расчета ПДВ (симплекс метод):');

 writeln(h,' ПРИМЕСЬ='+s);

 writeln(h,'');

 writeln(h,'---------------------------------------------------------');

 writeln(h,'| Решение не найдено |');

 writeln(h,'---------------------------------------------------------');

 end;

 closefile(h);

 end;

 // closefile(h);

 end;

end;

//==============================================================================

//поиск файла по маске

procedure FindFiles(StartFolder, Mask: string; List: TStrings;

 ScanSubFolders: Boolean = True);

var

 SearchRec: TSearchRec;

 FindResult: Integer;

begin

 List.BeginUpdate;

 try

 StartFolder := IncludeTrailingBackslash(StartFolder);

 FindResult := FindFirst(StartFolder + '*.*', faAnyFile, SearchRec);

 try

 while FindResult = 0 do

 with SearchRec do

 begin

 if (Attr and faDirectory) <> 0 then

 begin

 if ScanSubFolders and (Name <> '.') and (Name <> '..') then

 FindFiles(StartFolder + Name, Mask, List, ScanSubFolders);

 end

 else

 begin

 if MatchesMask(Name, Mask) then begin

 List.Add(copy(Name,5,4));

 //showmessage(StartFolder + Name);

 end;

 end;

 FindResult := FindNext(SearchRec);

 end;

 finally

 FindClose(SearchRec);

 end;

 finally

 List.EndUpdate;

 end;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

DecimalSeparator:=MyDecimalSeparator;

end;

procedure TForm1.FormActivate(Sender: TObject);

begin

dir_path:=ReadIni;

edit1.Text:=dir_path;

{--}

end;

procedure TForm1.BitBtn1Click(Sender: TObject);

var

 h,h2:textfile;

 i,j,k,n:integer;

 s_temp:string;

 s: array of array of string;

begin

 dir_path:=edit1.Text;

 checklistbox1.Items.Clear;

 i:=0;

 AssignFile(h,dir_path+'\WORK\activ2.txt');

 reset(h);

 //readln(h,s_temp);

 while not EOF(h) do begin//чтение файла (установка размера массива)

 readln(h,s_temp);

 inc(i);

 end;

 closefile(h);

 setlength(s,i,2);

 AssignFile(h2,dir_path+'\WORK\activ2.txt');

 reset(h2);

 for j:=0 to i-1 do begin

 readln(h2,s_temp);

 s[j,0]:=copy(s_temp,24,4);

 s[j,1]:=copy(s_temp,30,55);

 end;

 closefile(h2);

 FindFiles(dir_path, 'htop*.ppp', checklistbox1.items, true);

 n:=checklistbox1.items.Count-1;

 for j:=0 to n do begin

 for k:=0 to i-1 do begin

 //showmessage(s[k,0]+' -| ');

 if checklistbox1.items[0]=s[k,0] then begin

 //showmessage(s[j,0]+' | '+s[j,1]);

 checklistbox1.items.Delete(0);

 checklistbox1.items.Add(s[k,0]+' '+s[k,1]);

 end;

 end;

 end;

end;

procedure TForm1.N2Click(Sender: TObject);

var

 TitleName : string;

 lpItemID : PItemIDList;

 BrowseInfo : TBrowseInfo;

 DisplayName : array[0..MAX_PATH] of char;

 TempPath : array[0..MAX_PATH] of char;

begin

 FillChar(BrowseInfo, siCeof(TBrowseInfo), #0);

 BrowseInfo.hwndOwner := Form1.Handle;

 BrowseInfo.psCDisplayName := @DisplayName;

 TitleName := 'Please specify a directory';

 BrowseInfo.lpsCTitle := PChar(TitleName);

 BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;

 lpItemID := SHBrowseForFolder(BrowseInfo);

 if lpItemId <> nil then

 begin

 SHGetPathFromIDList(lpItemID, TempPath);

 edit1.Text:=TempPath;

 GlobalFreePtr(lpItemID);

 end;

//showmessage(tempPath);

dir_path:=tempPath;

//FindFiles(tempPath, 'htop*.ppp', checkmemo1.lines, true); //старая версия

SaveIni(dir_path);

end;

procedure TForm1.SpeedButton1Click(Sender: TObject);

var

 TitleName : string;

 lpItemID : PItemIDList;

 BrowseInfo : TBrowseInfo;

 DisplayName : array[0..MAX_PATH] of char;

 TempPath : array[0..MAX_PATH] of char;

begin

 FillChar(BrowseInfo, siCeof(TBrowseInfo), #0);

 BrowseInfo.hwndOwner := Form1.Handle;

 BrowseInfo.psCDisplayName := @DisplayName;

 TitleName := 'Please specify a directory';

 BrowseInfo.lpsCTitle := PChar(TitleName);

 BrowseInfo.ulFlags := BIF_RETURNONLYFSDIRS;

 lpItemID := SHBrowseForFolder(BrowseInfo);

 if lpItemId <> nil then

 begin

 SHGetPathFromIDList(lpItemID, TempPath);

 edit1.Text:=TempPath;

 GlobalFreePtr(lpItemID);

 end;

//showmessage(tempPath);

dir_path:=tempPath;

//FindFiles(tempPath, 'htop*.ppp', checkmemo1.lines, true); //старая версия

SaveIni(dir_path);

end;

procedure TForm1.SpeedButton2Click(Sender: TObject);

var

 i:integer;

begin

for i:=0 to checklistbox1.Items.Count-1 do

 checklistbox1.Checked[i]:=true;

end;

procedure TForm1.SpeedButton3Click(Sender: TObject);

var

 i:integer;

begin

for i:=0 to checklistbox1.Items.Count-1 do

 checklistbox1.Checked[i]:=false;

end;

procedure TForm1.SpeedButton4Click(Sender: TObject);

var

 i:integer;

begin

for i:=0 to checklistbox1.Items.Count-1 do

 if checklistbox1.Checked[i] then checklistbox1.Checked[i]:=false

 else checklistbox1.Checked[i]:=true;

end;

end.

Simplex.pas

unit simplex;

interface

const

 SIMPLEX_DONE = 0; // оптимизация успешно завершена

 SIMPLEX_NO_SOLUTION = 1; // задача не имеет решения (не удается найти базис)

 SIMPLEX_NO_BOTTOM = 2; // решения нет, т.к. линейная форма не ограничена снизу

 SIMPLEX_NEXT_STEP = 3; // для получения решения нужно сделать еще хотя бы один шаг

 MAX_VAL = 0.1e-12; //точность (значение, удовлетворяющее -MAX_VAL < X < MAX_VAL считается нулем)

type

 TOperation = (Equal,Less,Greater);

 TExtArray = array of extended;

 TConstrain = record

 A : TExtArray;

 B : extended;

 Sign : TOperation;

 isT : boolean;

 end;

 TSimplex = class

 M,N : integer; { M - число строк, N - число столбцов}

 RealN : integer; {реальное число переменных, изначально вошедших в задачу}

 Cons : array of TConstrain;

 C : TExtArray;

 L : extended;

 Basis : array of integer;

 Max : boolean; { направление оптимизации: минимизация или максимизация }

 Constructor Create(_C:TExtArray; MaximiCe:boolean=false);

 Constructor CreateBasis(const Simplex:TSimplex);

 Constructor Copy(const Simplex:TSimplex);

 Procedure AddCons(_B:extended; _A:TExtArray; Sign:TOperation);

 Procedure SetAllLengths(Len:integer);

 Function SimplexStep:integer;

 Function CheckBasis:boolean;

 Function FoundInBasis(num:integer): integer;

 Function DoPrec(num:extended): extended;

 Procedure NormaliCe;

 Procedure MulString(Number:integer; Value:extended);

 Procedure AddString(Num1,Num2:integer; Value:extended); {суммирование строки 1 со строкой 2, домноженной на коэффициент Value }

 Function Solve:integer;

 Function GetMin:extended;

 Function GetSolution:TExtArray;

 Destructor Free;

 end;

 TIntSimplex = class(TSimplex)

 // CurX : TExtArray;

 //CurL : extended;

 // CurFound : boolean;

 Constructor Create(_C:TExtArray; MaximiCe:boolean=false);

 // Procedure DelLastCons;

 Function IntSolve:integer;

 Function GetIntMin:extended;

 Function IsInteger(value:extended):boolean;

 Function GetIntSolution:TExtArray;

 // Function SearchCons(_B:extended;_A:TExtArray):integer;

 end;

implementation

uses Math;

{ TSimplex }

Function TSimplex.DoPrec(num:extended): extended;

begin

 if ((num < MAX_VAL) and (num > -MAX_VAL)) then

 num := 0;

 Result := num;

end;

procedure TSimplex.AddCons(_B: extended; _A: TExtArray; Sign: TOperation);

var

 j : integer;

begin

 if (Length(_A)>N) then SetAllLengths(Length(_A));

 inc(M);

 SetLength(Cons,M);

 //if ((_B=0) and (Sign=Less)) then Sign:=Equal; //???

 Cons[M-1].B:=_B;

 Cons[M-1].Sign:=Sign;

 SetLength(Cons[M-1].A,N);

 for j:=0 to Length(_A)-1 do Cons[M-1].A[j]:=_A[j];

 if Length(_A)<N then for j:=Length(_A) to N-1 do Cons[M-1].A[j]:=0;

end;

{суммирование строки 1 со строкой 2, домноженной на коэффициент Value }

procedure TSimplex.AddString(Num1, Num2: integer; Value: extended);

var

 j : integer;

begin

 for j:=0 to N-1 do Cons[Num1].A[j]:=Cons[Num1].A[j]+Cons[Num2].A[j]*Value;

 Cons[Num1].B:=Cons[Num1].B+Cons[Num2].B*Value;

end;

function TSimplex.CheckBasis: boolean;

var

 i,j,k : integer;

 f : boolean;

begin

 SetLength(Basis,M);

 for i:=0 to M-1 do Basis[i]:=-1;

 for j:=0 to N-1 do begin

 f:=true;

 k:=-1;

 i:=0;

 while (f and (i<M)) do begin

 if ((Cons[i].A[j]<>0) and (Cons[i].A[j]<>1)) then f:=false;

 if (Cons[i].A[j]=1) then begin

 if (k=-1) then k:=i

 else f:=false;

 end;

 inc(i);

 end;

 if (f and (k<>-1)) then Basis[k]:=j;

 end;

 f:=true;

 for i:=0 to M-1 do f:=f and (Basis[i]<>-1);

 Result:=f;

end;

constructor TSimplex.Create(_C: TExtArray; MaximiCe:boolean);

var

 j : integer;

begin

 N:=Length(_C);

 RealN := N;

 M:=0;

 SetLength(C,N);

 Max:=MaximiCe;

 if (not MaximiCe) then for j:=0 to N-1 do C[j]:=-_C[j]

 else for j:=0 to N-1 do C[j]:=_C[j];

 Max:=MaximiCe;

 L := 0;

end;

constructor TSimplex.Copy(const Simplex: TSimplex);

var

 i,j : integer;

begin

 M:=Simplex.M;

 N:=Simplex.N;

 RealN := Simplex.RealN;

 SetLength(Cons,M);

 SetLength(Basis,M);

 SetLength(C,N);

 Max:=Simplex.Max;

 for i:=0 to M-1 do begin

 SetLength(Cons[i].A,N);

 Basis[i]:=-1;

 for j:=0 to N-1 do Cons[i].A[j]:=Simplex.Cons[i].A[j];

 Cons[i].B:=Simplex.Cons[i].B;

 Cons[i].Sign:=Simplex.Cons[i].Sign;

 end;

 for i:=0 to Simplex.N-1 do C[i]:=Simplex.C[i];

 L := Simplex.L;

end;

constructor TSimplex.CreateBasis(const Simplex: TSimplex);

var

 i,j : integer;

begin

 M:=Simplex.M;

 N:=Simplex.N;

 RealN := Simplex.RealN;

 L := 0;

 SetLength(Cons,M);

 SetLength(Basis,M);

 SetLength(C,N);

 for i:=0 to N-1 do C[i]:=0;

 for i:=0 to M-1 do begin

 SetLength(Cons[i].A,N);

 for j:=0 to N-1 do Cons[i].A[j]:=Simplex.Cons[i].A[j];

 Cons[i].B:=Simplex.Cons[i].B;

 Cons[i].Sign:=equal;

 Cons[i].isT := false;

 end;

 for i:=0 to M-1 do begin

 if (Simplex.Basis[i]<>-1) then Basis[i]:=Simplex.Basis[i]

 else begin

 SetAllLengths(N+1);

 for j:=0 to M-1 do Cons[j].A[N-1]:=0;

 Cons[i].A[N-1]:=1;

 Cons[i].isT := true;

 C[N-1] := 0;

 for j:=0 to Simplex.N-1 do C[j] := C[j] + Simplex.Cons[i].A[j];

 L := L + Cons[i].B;

 end;

 end;

end;

destructor TSimplex.Free;

begin

 SetLength(C,0);

 SetLength(Basis,0);

 SetLength(Cons,0);

 M:=0;

 N:=0;

 RealN := 0;

end;

function TSimplex.GetMin: extended;

var

 i : integer;

begin

 if (Max) then

 Result := -L

 else

 Result := L;

end;

function TSimplex.GetSolution: TExtArray;

var

 Solution : TExtArray;

 i,j : integer;

begin

 SetLength(Solution,RealN);

 for j:=0 to RealN-1 do begin

 Solution[j]:=0;

 i:=0;

 while ((i<M) and (Basis[i]<>j)) do inc(i);

 if ((Basis[i]=j) and (i<M)) then Solution[j]:=Cons[i].B;

 end;

 Result:=Solution;

end;

procedure TSimplex.MulString(Number: integer; Value: extended);

var

 j : integer;

begin

 for j:=0 to N-1 do Cons[Number].A[j]:=Cons[Number].A[j]*Value;

 Cons[Number].B:=Cons[Number].B*Value;

end;

procedure TSimplex.NormaliCe;

var

 i : integer;

begin

 for i:=0 to M-1 do if (Cons[i].Sign<>Equal) then begin

 SetAllLengths(N+1);

 if (Cons[i].Sign=Greater) then Cons[i].A[N-1]:=-1

 else Cons[i].A[N-1]:=1;

 Cons[i].Sign := Equal;

 end;

end;

procedure TSimplex.SetAllLengths(Len: integer);

var

 i, j : integer;

 OldN : integer;

begin

 OldN:=N;

 N:=Len;

 SetLength(C,N);

 for i:=0 to M-1 do SetLength(Cons[i].A,N);

 if (OldN<N) then begin

 for j:=OldN to N-1 do begin

 C[j]:=0;

 for i:=0 to M-1 do Cons[i].A[j]:=0;

 end;

 end;

end;

function TSimplex.FoundInBasis(num:integer): integer;

var

 i:integer;

 f:boolean;

begin

 f := false;

 i := 0 ;

 while (not f and (i<M)) do

 begin

 f := (Basis[i] = num);

 inc(i);

 end;

 if (f) then

 Result := i-1

 else

 Result := -1;

end;

function TSimplex.SimplexStep: integer;

var

 i,j : integer;

 f,opt : boolean;

 x,y : integer; //координаты опорного элемента

 CurMax : extended;

 temp : array of TConstrain;

 tempC : TExtArray;

begin

 opt := true;

 CurMax := -1;

 for i := 0 to N-1 do

 begin

 //проверка на разрешимость

 if (C[i] > 0) then

 begin

 opt := false; //а это попутная проверка на оптимальность

 if (C[i] > CurMax) then //а это поиск ведущего столбца (максимальный элемент в C[i])

 begin

 CurMax := C[i];

 x := i;

 end;

 f := true;

 for j := 0 to M-1 do

 f := f and (Cons[j].A[i] < 0);

 if (f) then

 begin

 Result := SIMPLEX_NO_BOTTOM;

 exit;

 end;

 end;

 end;

 if (opt) then

 Result := SIMPLEX_DONE

 else

 begin

 //зная номер ведущего столбца, ищем номер ведущей строки

 CurMax := MaxExtended; //на самом деле тут будем искать минимум, а не Max

 for j := 0 to M-1 do

 if (Cons[j].A[x] > 0) then //идем только по положительным элементам

 if (Cons[j].B/Cons[j].A[x] < CurMax) then

 begin

 CurMax := Cons[j].B/Cons[j].A[x];

 y := j;

 end

 else if (DoPrec(Cons[j].B/Cons[j].A[x] - CurMax) = 0) then

 if (Cons[j].isT) then

 y := j;

 //сохраняем текущие значения

 SetLength(temp, M);

 for j := 0 to M-1 do

 begin

 SetLength(temp[j].A, N);

 for i := 0 to N-1 do

 temp[j].A[i] := Cons[j].A[i];

 temp[j].B := Cons[j].B;

 end;

 SetLength(tempC, N);

 for i := 0 to N-1 do

 tempC[i] := C[i];

 //делаем пересчет таблицы

 //строка делиться на ведущий элемент

 MulString(y, 1/Cons[y].A[x]);

 //преобразование остальных элементов

 for j := 0 to M-1 do

 begin

 if (j <> y) then

 begin

 for i := 0 to N-1 do

 begin

 Cons[j].A[i] := DoPrec(temp[j].A[i] - temp[j].A[x]*temp[y].A[i]/temp[y].A[x]);

 end;

 Cons[j].B := DoPrec(temp[j].B - temp[j].A[x]*temp[y].B/temp[y].A[x]);

 end

 else

 begin

 for i := 0 to N-1 do

 Cons[j].A[i] := DoPrec(Cons[j].A[i]);

 end;

 end;

 //и строка с коэффициентами функции

 for i := 0 to N-1 do

 begin

 C[i] := DoPrec(tempC[i] - tempC[x]*temp[y].A[i]/temp[y].A[x]);

 end;

 Basis[y] := x;

 //и сама функция:

 L := DoPrec(L - tempC[x]*temp[y].B/temp[y].A[x]);

 for i:= 0 to M-1 do

 SetLength(temp[i].A, 0);

 SetLength(temp, 0);

 SetLength(tempC, 0);

 Result := SIMPLEX_NEXT_STEP;

 end;

end;

function TSimplex.Solve: integer;

var

 i,j : integer;

 Simplex : TSimplex;

 f : boolean;

 Step : integer;

 cc : extended;

begin

 //oldN := N;

 NormaliCe;

 f:=false;

 if (not CheckBasis) then begin

 Simplex:=TSimplex.CreateBasis(self);

 Simplex.Solve;

 f:=Simplex.GetMin<>0;

 if (not f) then for i:=0 to M-1 do begin

 for j:=0 to N-1 do Cons[i].A[j]:=Simplex.Cons[i].A[j];

 Cons[i].B:=Simplex.Cons[i].B;

 Cons[i].isT := false;

 Basis[i]:=Simplex.Basis[i];

 cc := C[Basis[i]];

 for j:=0 to N-1 do

 C[j] := DoPrec(C[j] - cc*Cons[i].A[j]);

 L := DoPrec(L - cc*Cons[i].B);

 end;

 Simplex.Free;

 end;

 if (f) then Step:=SIMPLEX_NO_SOLUTION

 else repeat

 Step:=SimplexStep;

 until (Step<>SIMPLEX_NEXT_STEP);

 //SetAllLengths(OldN);

 Result:=Step;

end;

{ TIntSimplex }

constructor TIntSimplex.Create(_C:TExtArray; MaximiCe:boolean=false);

begin

 //CurFound:=false;

 inherited;

end;

function TIntSimplex.GetIntMin: extended;

begin

 Result:=GetMin;

end;

function TIntSimplex.GetIntSolution: TExtArray;

begin

 Result:=GetSolution;

end;

function TIntSimplex.IsInteger(Value:extended):boolean;

begin

 Result:=((Value=floor(Value)) or (Value=ceil(Value)));

end;

function TIntSimplex.IntSolve: integer;

var

 i : integer;

 OldN : integer;

 FractCol : integer;

 FractRow : integer;

 TmpX : TExtArray;

 TmpCons : TExtArray;

 NewValue : extended;

begin

 if (Solve=SIMPLEX_DONE) then begin

 //if (not CurFound or ((Simplex.GetMin<CurL) and not Max) or ((Simplex.GetMin>CurL) and Max)) then begin

 TmpX:=GetSolution;

 i:=0;

 while ((i<RealN) and IsInteger(TmpX[i])) do inc(i);

 FractCol:=i;

 if (FractCol<>RealN) then begin // если найдена хотя бы одна нецелая переменная

 OldN:=N;

 SetLength(TmpCons,N);

 FractRow := FoundInBasis(FractCol);

 for i := 0 to N-1 do

 if (FoundInBasis(i) = -1) then

 TmpCons[i] := Cons[FractRow].A[i] - Floor(Cons[FractRow].A[i])

 else

 TmpCons[i] := 0;

 NewValue := Cons[FractRow].B - Floor(Cons[FractRow].B);

 //if (Max) then

 AddCons(NewValue, TmpCons, Greater);

 //else

 // AddCons(NewValue, TmpCons, Less);

 Result := IntSolve;

 SetAllLengths(OldN); // удаляем пустые столбцы в конце, если они есть

 end

 else begin // если полученное решение - целочисленное\

 Result := SIMPLEX_DONE;

 end;

 //end;

 end

 else

 Result:=SIMPLEX_NO_SOLUTION;

end;

end.


Информация о работе «Разработка программного модуля для нахождения оптимальных предельно-допустимых выбросов в атмосферу от группы источников»
Раздел: Экология
Количество знаков с пробелами: 96043
Количество таблиц: 2
Количество изображений: 4

Похожие работы

Скачать
229109
11
0

... экспертов ГЭЭ", "О государственной экспертизе градостро-ительной и проектно-сметной документации и утверждении проектов строительства", "Об утвер-ждении Положения о государственной экологической экспертизе" (п.п.14 и 15), "Об утверждении Временного положения о финансировании и кредитовании капитального строительства на территории РФ", "Об утверждении Положения о порядке подготовки, рассмотрения и ...

Скачать
79372
29
0

... r=ro определяем тепловой коэффициент F(ro); отношение r/Zo,j= 0,7/9,0=0,078 1 F(ro)= ----- Y(r/Zo,r/Zo,j) 2l37l F(ro) = 0,37 град/Вт Температура в точке r=ro составляет t(ro)7tc = P7F(ro) t(ro) = 70,6 град tc принимается равной to устройства и равно 70o. Рассчитываем коэффициент F(r/Zo) для следующих точек: r/Zo=0,2;0,3;0,6;1. Из таблиц находим функцию Y для этих точек: Y(0,2)=0,228 ...

Скачать
166317
25
0

... предварительного сброса воды № 3 НГДУ «Мамонтовнефть» при максимальной пропускной способности оборудования На основании поверочного технологического расчета составлен материальный баланс установки предварительного сброса воды № 3 НГДУ «Мамонтовнефть» при максимальной пропускной способности оборудования по сырью табл. 12. Число рабочих дней в году 365. Таблица 12 Материальный баланс базовой ...

Скачать
237725
5
0

... бумажными технологиями). Третий этап. Внедрение самостоятельного электронного документооборота. Организация работы арендуемых приложений.4.3   Создание Информационно-логистического центра транспортного комплекса калининградского региона   4.3.1           Организационная модель ИЛЦ   4.3.1.1       Закрытое акционерное общество "Информационно-логистический Центр" Акционерная компания ( ...

0 комментариев


Наверх