| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- unit CORE; {Ядро модели системы массового обслуживания}
- INTERFACE
- type
- PSource = ^CSource; {Указатель на источник}
- PDevice = ^CDevice; {Указатель на систему обработки (устройство) }
- PBuffer = ^CBuffer; {Указатель на буфер запросов}
- {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- TReq = record {Запрос на обслуживание}
- Birth : real; {Время появления запроса}
- Death : real; {Время смерти запроса (обработан, либо отклонен)}
- FromSource : PSource; {Кто просил-то ?}
- ToDevice : PDevice; {А собственно куда ?}
- end;
- {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- {$R-}
- TReqArray = array [0..1000] of TReq;
- PReqArray = ^TReqArray;
- TSourceArr = array [0..1000] of PSource;
- PSourceArr = ^TSourceArr;
- PReq = ^TReq;
- {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- ESOURCES = (SOURCE_DUMMY,SOURCE_EASIEST,SOURCE_ERLANG); {Типы источников}
- CSource = object {Объект - простейший источник}
- SType : ESOURCES; {Каков наш источник? }
- Name : integer; {А как его зовут ?}
- LastTime : real; {Время генерации последнего запроса}
- LastReq : TReq; {Последний сгенерированный запрос}
- NewTime : real; {Момент генерации нового запроса}
- Lambda : real;
- TotalReq : longInt; {Общее число заявок от источника}
- DoneReq : longInt; {число обработанных заявок от источника}
- RefusedReq:LongInt; {Число отклоненных заявок}
- WaitTime : real; {Общее время пребывания в системе}
- ProbRefuse:real; {Вероятность отказа}
- MatWait : real; {Математическое ожидание в буфере}
- Constructor Init(aName : Integer;aLambda:real); {Конструктор с именем}
- Procedure Reset; {Сброс всех счетчиков}
- Procedure GenNewReq; {Генерация нового запроса}
- Destructor Done;virtual;
- end;{CSource}
- {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- CDevice = object {Объект - простейшее устойство массового обслуживания}
- LastTime : real; {Время последнего завершения обслуживания}
- BegTime : real; {Время начала обслуживания}
- DoneTime : real; {Время, в которое закончится обработка}
- Stoppage : real; {Общее время простоя прибора}
- IsWorking : boolean; {Осуществляется ли обслуживание ?}
- CurWorking : TReq; {Текущий обрабатываемый запрос}
- Lambda : real;
- Constructor Init(aLambda:real); {}
- Function AddReq(aCurReq : PReq;aCurTime:real):boolean; {Начало обработка запроса}
- Procedure Reset; {Сброс устр-ва}
- Function DoneWork:PReq; {Завершение обработки текущего запроса, с его возвратом}
- Destructor Done;
- end; {CDevice}
- {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- EBuffers = (BUFFER_DUMMY, BUFFER_FIFO, BUFFER_LIFO);
- CBuffer = object {Буффер запросов}
- BufType : EBuffers; {Тип буфера}
- BufferLength : integer; {Длина буфера}
- CellCount : integer; {Индекс текущей свободной ячейки}
- Data : PReqArray; {Собственно сам буфер}
- Constructor Init(aBufLen:integer); {Инициализация буфера}
- Destructor Done;virtual;{Деструктор, он и есть}
- Function SetBufferSize(aNewSize:integer):boolean;{Изменение размера буфера}
- Procedure FreeBuffer; {Освобождение всего буфера сразу}
- Function AddReq(var aNew, rKicked:TReq):boolean; {Добавляется запрос в буфер.
- Если из буфера какой-то запрос удален, то ф-ция возвр. false, и в rKicked -
- запрос, который отклонен}
- Function GetReq(var rReq:TReq):boolean;virtual; {Вытащить из буфера запрос,
- если успешно - true}
- end; {CBuffer}
- {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- CModel = object {Наша модель СМО}
- Sources : PSourceArr; {Источники}
- SourceCnt: integer; {Число источников}
- MaxSrc : integer; {Размерность массива источников}
- Buffer : PBuffer; {Буфер}
- Device : PDevice; {Устройство}
- CurTime : real; {Текущий момент времени}
- Delta : real;
- DovInt : real;
- NextSource:integer; {Какой из источников - быстрее}
- RealizSteps:LongInt; {Необх. число реализаций}
- CurStep : LongInt; {Текущий шаг}
- {}
- DoneCount, {Число обработанных заявок}
- RefusedCount, {Число отклоненных заявок}
- TotalCount : integer; {Общее число заявок}
- Working : boolean; {Работает ли модель ?}
- WorkReq : TReq;
- Constructor Init(aBegSrcCnt:integer;aDev:PDevice;aBuf:PBuffer;
- aDel,aDov:Real);
- Function SetSourceCount(aNewCnt:integer):boolean; {Установка нового числа
- источников, с сохранением старых}
- Function AddNewSource(aNewSrc:PSource):boolean; {Добавление нового источника}
- Procedure SetNextSource; {Находит NextSource}
- Function TestVer:boolean; {}
- Function RemoveSource(aName:integer):boolean; {Удаление источника из модели}
- Procedure Reset; {Сброс всех счетчиков}
- Procedure Start;
- Procedure PrintValues(var F:TEXT);
- Function Step:boolean; {Моделирует следующий шаг, если в }
- Destructor Done;
- end;
- {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- IMPLEMENTATION
- Constructor CSource.Init(aName : Integer;aLambda:real);
- Begin
- Name := aName;
- SType := SOURCE_EASIEST;
- Lambda := aLambda;
- Reset;
- end;{CSource.Init}
- {-------------------------------------------------------------------------}
- Procedure CSource.Reset;
- Begin
- LastTime :=0; NewTime:=0;
- TotalReq :=0;
- DoneReq :=0;
- RefusedReq:=0;
- WaitTime :=0;
- ProbRefuse:=0;
- MatWait :=0;
- end;{CSource.Reset}
- {-------------------------------------------------------------------------}
- Procedure CSource.GenNewReq;
- Begin
- LastTime := NewTime;
- NewTime := LastTime - Ln(Random)/Lambda;
- Inc(TotalReq);
- LastReq.Birth := NewTime;
- LastReq.Death := -1.0;
- LastReq.FromSource := @Self;
- end;{CSource.GenNewReq}
- {-------------------------------------------------------------------------}
- Destructor CSource.Done;
- begin
- end;
- {-------------------------------------------------------------------------}
- { CDevice }
- Constructor CDevice.Init(aLambda:real);
- begin
- Lambda := aLambda;
- Reset;
- end;{CDevice.Init}
- {=========================================}
- Procedure CDevice.Reset;
- begin
- LastTime := 0;
- DoneTime := 0;
- Stoppage := 0;
- IsWorking := false;
- end;{CDevice.Reset}
- {---------------------------}
- Function CDevice.AddReq(aCurReq : PReq;aCurTime:real):boolean; {Начало обработка запроса}
- begin
- AddReq := false;
- if not isWorking then
- begin
- BegTime := aCurTime;
- Stoppage := Stoppage + (BegTime-LastTime);
- DoneTime := BegTime - Ln(Random)/Lambda;
- IsWorking := true;
- CurWorking := aCurReq^;
- CurWorking.ToDevice := @Self;
- AddReq := true;
- end;
- end;{CDevice.AddReq}
- {=========================================}
- Function CDevice.DoneWork:PReq;
- begin
- DoneWork := nil;
- if isWorking then
- begin
- LastTime := DoneTime;
- CurWorking.Death := DoneTime;
- DoneWork := @CurWorking;
- isWorking := false;
- end;
- end;{CDevice.DoneWork}
- {=========================================}
- Destructor CDevice.Done;
- begin
- end;{CDevice.Done}
- {=========================================}
- { CBuffer }
- Constructor CBuffer.Init(aBufLen:integer);
- begin
- BufType := BUFFER_LIFO;
- BufferLength := aBufLen;
- CellCount := 0;
- GetMem(Data,Sizeof(TReq)*BufferLength);
- FillChar(Data^,Sizeof(TReq)*BufferLength,0);
- end;{CBuffer.Init}
- {-----------------------}
- Destructor CBuffer.Done;
- begin
- FreeMem(Data,Sizeof(TReq)*BufferLength); {Dispose(data)}
- BufferLength:=0;
- end;{CBuffer.Done}
- {-----------------------}
- Function CBuffer.SetBufferSize(aNewSize:integer):boolean;
- var
- NewBuf : PReqArray;
- begin
- SetBufferSize := false;
- if aNewSize > BufferLength then
- begin
- GetMem(NewBuf,Sizeof(TReq)*aNewSize);
- FillChar(NewBuf^,Sizeof(TReq)*aNewSize,0);
- Move(Data^,NewBuf^,Sizeof(TReq)*BufferLength);
- FreeMem(Data,Sizeof(TReq)*BufferLength);
- Data := NewBuf;
- BufferLength := aNewSize;
- SetBufferSize := true;
- end;
- end;{CBuffer.SetBufferSize}
- {-----------------------}
- Function CBuffer.AddReq(var aNew, rKicked:TReq):boolean;
- begin
- if CellCount=BufferLength then {На самом деле, т.к с 0, то больше}
- begin
- AddReq := false;
- rKicked := Data^[0];
- rKicked.Death := aNew.Birth; {Запрос отклонен, в момент, когда новый прибыл,
- т.е. когда тот был создан}
- Move(Data^[1],Data^[0], SizeOf(TReq) * (BufferLength-1));
- Data^[CellCount-1] := aNew;
- end
- else
- begin
- AddReq := true;
- Data^[CellCount] := aNew;
- Inc(CellCount);
- end;
- end;{CBuffer.AddReq}
- {-----------------------}
- Function CBuffer.GetReq(var rReq:TReq):boolean;
- begin
- GetReq := false;
- if CellCount > 0 then
- begin
- rReq := Data^[CellCount-1];
- Dec(CellCount);
- GetReq := true;
- end;
- end;{CBuffer.GetReq}
- {---------------------------------------------}
- Procedure CBuffer.FreeBuffer;
- begin
- CellCount := 0;
- end;
- {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
- Constructor CModel.Init(aBegSrcCnt:integer;aDev:PDevice;aBuf:PBuffer;
- aDel,aDov:Real);
- Begin
- MaxSrc := aBegSrcCnt;
- GetMem(Sources,Sizeof(PSource)*MaxSrc);
- SourceCnt := 0;
- RealizSteps := 100;
- Buffer := aBuf;
- Device := aDev;
- Delta := aDel;
- DovInt := aDov;
- Reset;
- end;{CModel.Init}
- {---------------------------------------------------------}
- Procedure CModel.Reset;
- begin
- NextSource:=0;
- CurTime := 0;
- CurStep := 0;
- DoneCount := 0;
- RefusedCount := 0;
- RealizSteps := 100;
- TotalCount := 0;
- Working := false;
- end;{CModel.Reset}
- {------------------------------------------------------------------}
- Function CModel.SetSourceCount(aNewCnt:integer):boolean;
- var
- NewBuf : PSourceArr;
- Begin
- SetSourceCount := false;
- if aNewCnt > MaxSrc then
- begin
- GetMem(NewBuf,Sizeof(PSource)*aNewCnt);
- Move(Sources^,NewBuf^,Sizeof(PSource)*MaxSrc);
- FreeMem(Sources,Sizeof(PSource)*MaxSrc);
- Sources := NewBuf;
- MaxSrc := aNewCnt;
- SetSourceCount := true;
- end;
- end;{CModel.SetSourceCount}
- {------------------------------------------------------------------}
- Function CModel.AddNewSource(aNewSrc:PSource):boolean;
- Begin
- if SourceCnt >= MaxSrc then AddNewSource := SetSourceCount(MaxSrc+1);
- Sources^[SourceCnt] := aNewSrc;
- Inc(SourceCnt);
- end;{CModel.AddNewSource}
- {------------------------------------------------------------------}
- Function CModel.RemoveSource(aName:integer):boolean;
- var
- c : integer;
- Begin
- RemoveSource := false;
- if SourceCnt = 1 then exit;
- for c := 0 to SourceCnt-1 do if Sources^[c]^.Name = aName then break;
- if c = SourceCnt-1 then exit;
- Dispose(Sources^[c],Done);
- while c <> SourceCnt-1 do
- begin
- Sources^[c] := Sources^[c+1];
- inc(c);
- end;
- Dec(SourceCnt);
- end;{CModel.RemoveSource}
- {------------------------------------------------------------------}
- Procedure CModel.SetNextSource; {Находит NextSource}
- var
- c : integer;
- begin
- NextSource := 0;
- for c := 0 to SourceCnt-1 do
- begin
- if (Sources^[c]^.NewTime < Sources^[NextSource]^.NewTime) then
- NextSource := c;
- end;
- end;{CModel.SetNextSource}
- {------------------------------------------------------------------}
- Procedure CModel.Start;
- var
- c,First : integer;
- begin
- if (Device=nil) or (Buffer=nil) or (SourceCnt=0) then exit;
- Reset;
- Device^.Reset;
- Buffer^.FreeBuffer;
- First := 0;
- for c := 0 to SourceCnt-1 do
- begin
- Sources^[c]^.Reset;
- Sources^[c]^.GenNewReq;
- if (Sources^[c]^.NewTime < Sources^[First]^.NewTime) then
- First := c;
- end;
- WorkReq := Sources^[First]^.LastReq;
- Device^.AddReq(@WorkReq,Sources^[First]^.NewTime);
- Sources^[First]^.GenNewReq;
- SetNextSource;
- Working := true;
- end;
- {------------------------------------------------------------------}
- Function CModel.TestVer:boolean;
- var
- NewV,c,p:real;
- i : integer;
- begin
- NewV:=0;
- TestVer:=true;
- for i := 0 to SourceCnt-1 do if Sources^[i]^.RefusedReq <> 0 then
- begin
- p := 1.0 * Sources^[i]^.RefusedReq / Sources^[i]^.TotalReq;
- c := (DovInt*(1-p))/(Delta*Delta*p);
- if c > NewV then NewV := c;
- end;
- if NewV > RealizSteps then
- begin
- RealizSteps := round(NewV);
- TestVer := false;
- end;
- end;{CModel.TextVer}
- {------------------------------------------------------------------}
- Function CModel.Step:boolean;
- var
- Kicked : TReq;
- i : integer;
- ret : boolean;
- Begin
- Step := false;
- if Not Working then exit;
- ret := false; {Считаем, что продолжать не будем}
- for i:=0 to SourceCnt-1 do if Sources^[i]^.TotalReq < RealizSteps then
- ret:=true;
- if not ret then ret := not TestVer;
- if Device^.DoneTime < Sources^[NextSource]^.NewTime then
- begin
- CurTime := Device^.DoneTime;
- WorkReq := Device^.DoneWork^;
- inc(DoneCount);
- inc(TotalCount);
- inc(WorkReq.FromSource^.DoneReq);
- WorkReq.FromSource^.WaitTime := WorkReq.FromSource^.WaitTime +
- WorkReq.Death - WorkReq.Birth;
- if Buffer^.GetReq(WorkReq) then
- begin {В буфере находилась заявка}
- WorkReq.FromSource^.MatWait := WorkReq.FromSource^.MatWait +
- CurTime-WorkReq.Birth;
- Device^.AddReq(@WorkReq,CurTime);
- end
- else {Need to gen new req}
- begin
- Device^.AddReq(@Sources^[NextSource]^.LastReq,Sources^[NextSource]^.LastReq.Birth);
- Sources^[NextSource]^.GenNewReq;
- SetNextSource;
- end;
- end
- else {Ближайшее событие - генерация запроса}
- begin
- CurTime := Sources^[NextSource]^.NewTime;
- if not Buffer^.AddReq(Sources^[NextSource]^.LastReq,Kicked) then
- begin
- inc(Kicked.FromSource^.RefusedReq);
- {Kicked.FromSource^.WaitTime := Kicked.FromSource^.WaitTime +
- Kicked.Death-Kicked.Birth;}
- Inc(RefusedCount);
- Inc(TotalCount);
- end;
- Sources^[NextSource]^.GenNewReq;
- SetNextSource;
- end; {}
- inc(CurStep);
- Step := ret;
- end;{CModel.Step}
- {------------------------------------------------------------------}
- Procedure CModel.PrintValues(var F:Text);
- var
- i : integer;
- begin
- WriteLn(F,'Отн. точность - ',Delta*100:0:0,'%, дов. инт в кв. - ',DovInt:0:2);
- WriteLn(F,'Хар-ка потока прибора - ', Device^.Lambda:0:2);
- WriteLn(F,'Ист.|Всг заяв.|Отк заяв.|Вып заяв.|P отк. |Мат. ож | Общ. вр.');
- for i := 0 to SourceCnt-1 do with Sources^[i]^ do
- begin
- write(F,Name:4,' ',TotalReq:9,' ',RefusedReq:9,' ',DoneReq:9,' ',100.0*RefusedReq/TotalReq:6:2,'% ');
- if DoneReq <> 0 then Write(F,MatWait/DoneReq:8:3,' ') else Write(F,' --- ');
- WriteLN(F,WaitTime:0:2);
- end;
- WriteLn(F,'Коэффициент простоя прибора - ',100*Device^.Stoppage/CurTime:0:2,'%');
- WriteLN(F,'---')
- end;{CModel.PrintValues}
- {------------------------------------------------------------------}
- Destructor CModel.Done;
- var
- c : integer;
- Begin
- for c:= 0 to SourceCnt-1 do Dispose(Sources^[c],Done);
- FreeMem(Sources,Sizeof(PSource)*MaxSrc);
- end;{CModel.Done}
- {------------------------------------------------------------------}
- END. {EOF}
|