CORE.PAS 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. unit CORE; {Ядро модели системы массового обслуживания}
  2. INTERFACE
  3. type
  4. PSource = ^CSource; {Указатель на источник}
  5. PDevice = ^CDevice; {Указатель на систему обработки (устройство) }
  6. PBuffer = ^CBuffer; {Указатель на буфер запросов}
  7. {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  8. TReq = record {Запрос на обслуживание}
  9. Birth : real; {Время появления запроса}
  10. Death : real; {Время смерти запроса (обработан, либо отклонен)}
  11. FromSource : PSource; {Кто просил-то ?}
  12. ToDevice : PDevice; {А собственно куда ?}
  13. end;
  14. {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  15. {$R-}
  16. TReqArray = array [0..1000] of TReq;
  17. PReqArray = ^TReqArray;
  18. TSourceArr = array [0..1000] of PSource;
  19. PSourceArr = ^TSourceArr;
  20. PReq = ^TReq;
  21. {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  22. ESOURCES = (SOURCE_DUMMY,SOURCE_EASIEST,SOURCE_ERLANG); {Типы источников}
  23. CSource = object {Объект - простейший источник}
  24. SType : ESOURCES; {Каков наш источник? }
  25. Name : integer; {А как его зовут ?}
  26. LastTime : real; {Время генерации последнего запроса}
  27. LastReq : TReq; {Последний сгенерированный запрос}
  28. NewTime : real; {Момент генерации нового запроса}
  29. Lambda : real;
  30. TotalReq : longInt; {Общее число заявок от источника}
  31. DoneReq : longInt; {число обработанных заявок от источника}
  32. RefusedReq:LongInt; {Число отклоненных заявок}
  33. WaitTime : real; {Общее время пребывания в системе}
  34. ProbRefuse:real; {Вероятность отказа}
  35. MatWait : real; {Математическое ожидание в буфере}
  36. Constructor Init(aName : Integer;aLambda:real); {Конструктор с именем}
  37. Procedure Reset; {Сброс всех счетчиков}
  38. Procedure GenNewReq; {Генерация нового запроса}
  39. Destructor Done;virtual;
  40. end;{CSource}
  41. {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  42. CDevice = object {Объект - простейшее устойство массового обслуживания}
  43. LastTime : real; {Время последнего завершения обслуживания}
  44. BegTime : real; {Время начала обслуживания}
  45. DoneTime : real; {Время, в которое закончится обработка}
  46. Stoppage : real; {Общее время простоя прибора}
  47. IsWorking : boolean; {Осуществляется ли обслуживание ?}
  48. CurWorking : TReq; {Текущий обрабатываемый запрос}
  49. Lambda : real;
  50. Constructor Init(aLambda:real); {}
  51. Function AddReq(aCurReq : PReq;aCurTime:real):boolean; {Начало обработка запроса}
  52. Procedure Reset; {Сброс устр-ва}
  53. Function DoneWork:PReq; {Завершение обработки текущего запроса, с его возвратом}
  54. Destructor Done;
  55. end; {CDevice}
  56. {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  57. EBuffers = (BUFFER_DUMMY, BUFFER_FIFO, BUFFER_LIFO);
  58. CBuffer = object {Буффер запросов}
  59. BufType : EBuffers; {Тип буфера}
  60. BufferLength : integer; {Длина буфера}
  61. CellCount : integer; {Индекс текущей свободной ячейки}
  62. Data : PReqArray; {Собственно сам буфер}
  63. Constructor Init(aBufLen:integer); {Инициализация буфера}
  64. Destructor Done;virtual;{Деструктор, он и есть}
  65. Function SetBufferSize(aNewSize:integer):boolean;{Изменение размера буфера}
  66. Procedure FreeBuffer; {Освобождение всего буфера сразу}
  67. Function AddReq(var aNew, rKicked:TReq):boolean; {Добавляется запрос в буфер.
  68. Если из буфера какой-то запрос удален, то ф-ция возвр. false, и в rKicked -
  69. запрос, который отклонен}
  70. Function GetReq(var rReq:TReq):boolean;virtual; {Вытащить из буфера запрос,
  71. если успешно - true}
  72. end; {CBuffer}
  73. {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  74. CModel = object {Наша модель СМО}
  75. Sources : PSourceArr; {Источники}
  76. SourceCnt: integer; {Число источников}
  77. MaxSrc : integer; {Размерность массива источников}
  78. Buffer : PBuffer; {Буфер}
  79. Device : PDevice; {Устройство}
  80. CurTime : real; {Текущий момент времени}
  81. Delta : real;
  82. DovInt : real;
  83. NextSource:integer; {Какой из источников - быстрее}
  84. RealizSteps:LongInt; {Необх. число реализаций}
  85. CurStep : LongInt; {Текущий шаг}
  86. {}
  87. DoneCount, {Число обработанных заявок}
  88. RefusedCount, {Число отклоненных заявок}
  89. TotalCount : integer; {Общее число заявок}
  90. Working : boolean; {Работает ли модель ?}
  91. WorkReq : TReq;
  92. CalcVer : boolean; {Нужно ли подсчитывать KMIN в зав. от вер ?}
  93. Constructor Init(aBegSrcCnt:integer;aDev:PDevice;aBuf:PBuffer;
  94. aDel,aDov:Real);
  95. Function SetSourceCount(aNewCnt:integer):boolean; {Установка нового числа
  96. источников, с сохранением старых}
  97. Function AddNewSource(aNewSrc:PSource):boolean; {Добавление нового источника}
  98. Procedure SetNextSource; {Находит NextSource}
  99. Function TestVer:boolean; {}
  100. Function RemoveSource(aName:integer):boolean; {Удаление источника из модели}
  101. Procedure Reset; {Сброс всех счетчиков}
  102. Procedure Start;
  103. Procedure PrintValues(var F:TEXT);
  104. Function Step:boolean; {Моделирует следующий шаг, если в }
  105. Destructor Done;
  106. end;
  107. {-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  108. IMPLEMENTATION
  109. Constructor CSource.Init(aName : Integer;aLambda:real);
  110. Begin
  111. Name := aName;
  112. SType := SOURCE_EASIEST;
  113. Lambda := aLambda;
  114. Reset;
  115. end;{CSource.Init}
  116. {-------------------------------------------------------------------------}
  117. Procedure CSource.Reset;
  118. Begin
  119. LastTime :=0; NewTime:=0;
  120. TotalReq :=0;
  121. DoneReq :=0;
  122. RefusedReq:=0;
  123. WaitTime :=0;
  124. ProbRefuse:=0;
  125. MatWait :=0;
  126. end;{CSource.Reset}
  127. {-------------------------------------------------------------------------}
  128. Procedure CSource.GenNewReq;
  129. Begin
  130. LastTime := NewTime;
  131. NewTime := LastTime - Ln(Random)/Lambda;
  132. Inc(TotalReq);
  133. LastReq.Birth := NewTime;
  134. LastReq.Death := -1.0;
  135. LastReq.FromSource := @Self;
  136. end;{CSource.GenNewReq}
  137. {-------------------------------------------------------------------------}
  138. Destructor CSource.Done;
  139. begin
  140. end;
  141. {-------------------------------------------------------------------------}
  142. { CDevice }
  143. Constructor CDevice.Init(aLambda:real);
  144. begin
  145. Lambda := aLambda;
  146. Reset;
  147. end;{CDevice.Init}
  148. {=========================================}
  149. Procedure CDevice.Reset;
  150. begin
  151. LastTime := 0;
  152. DoneTime := 0;
  153. Stoppage := 0;
  154. IsWorking := false;
  155. end;{CDevice.Reset}
  156. {---------------------------}
  157. Function CDevice.AddReq(aCurReq : PReq;aCurTime:real):boolean; {Начало обработка запроса}
  158. begin
  159. AddReq := false;
  160. if not isWorking then
  161. begin
  162. BegTime := aCurTime;
  163. Stoppage := Stoppage + (BegTime-LastTime);
  164. DoneTime := BegTime - Ln(Random)/Lambda;
  165. IsWorking := true;
  166. CurWorking := aCurReq^;
  167. CurWorking.ToDevice := @Self;
  168. AddReq := true;
  169. end;
  170. end;{CDevice.AddReq}
  171. {=========================================}
  172. Function CDevice.DoneWork:PReq;
  173. begin
  174. DoneWork := nil;
  175. if isWorking then
  176. begin
  177. LastTime := DoneTime;
  178. CurWorking.Death := DoneTime;
  179. DoneWork := @CurWorking;
  180. isWorking := false;
  181. end;
  182. end;{CDevice.DoneWork}
  183. {=========================================}
  184. Destructor CDevice.Done;
  185. begin
  186. end;{CDevice.Done}
  187. {=========================================}
  188. { CBuffer }
  189. Constructor CBuffer.Init(aBufLen:integer);
  190. begin
  191. BufType := BUFFER_LIFO;
  192. BufferLength := aBufLen;
  193. CellCount := 0;
  194. GetMem(Data,Sizeof(TReq)*BufferLength);
  195. FillChar(Data^,Sizeof(TReq)*BufferLength,0);
  196. end;{CBuffer.Init}
  197. {-----------------------}
  198. Destructor CBuffer.Done;
  199. begin
  200. FreeMem(Data,Sizeof(TReq)*BufferLength); {Dispose(data)}
  201. BufferLength:=0;
  202. end;{CBuffer.Done}
  203. {-----------------------}
  204. Function CBuffer.SetBufferSize(aNewSize:integer):boolean;
  205. var
  206. NewBuf : PReqArray;
  207. begin
  208. SetBufferSize := false;
  209. if aNewSize > BufferLength then
  210. begin
  211. GetMem(NewBuf,Sizeof(TReq)*aNewSize);
  212. FillChar(NewBuf^,Sizeof(TReq)*aNewSize,0);
  213. Move(Data^,NewBuf^,Sizeof(TReq)*BufferLength);
  214. FreeMem(Data,Sizeof(TReq)*BufferLength);
  215. Data := NewBuf;
  216. BufferLength := aNewSize;
  217. SetBufferSize := true;
  218. end;
  219. end;{CBuffer.SetBufferSize}
  220. {-----------------------}
  221. Function CBuffer.AddReq(var aNew, rKicked:TReq):boolean;
  222. begin
  223. if CellCount=BufferLength then {На самом деле, т.к с 0, то больше}
  224. begin
  225. AddReq := false;
  226. rKicked := Data^[0];
  227. rKicked.Death := aNew.Birth; {Запрос отклонен, в момент, когда новый прибыл,
  228. т.е. когда тот был создан}
  229. Move(Data^[1],Data^[0], SizeOf(TReq) * (BufferLength-1));
  230. Data^[CellCount-1] := aNew;
  231. end
  232. else
  233. begin
  234. AddReq := true;
  235. Data^[CellCount] := aNew;
  236. Inc(CellCount);
  237. end;
  238. end;{CBuffer.AddReq}
  239. {-----------------------}
  240. Function CBuffer.GetReq(var rReq:TReq):boolean;
  241. begin
  242. GetReq := false;
  243. if CellCount > 0 then
  244. begin
  245. rReq := Data^[CellCount-1];
  246. Dec(CellCount);
  247. GetReq := true;
  248. end;
  249. end;{CBuffer.GetReq}
  250. {---------------------------------------------}
  251. Procedure CBuffer.FreeBuffer;
  252. begin
  253. CellCount := 0;
  254. end;
  255. {-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-}
  256. Constructor CModel.Init(aBegSrcCnt:integer;aDev:PDevice;aBuf:PBuffer;
  257. aDel,aDov:Real);
  258. Begin
  259. MaxSrc := aBegSrcCnt;
  260. GetMem(Sources,Sizeof(PSource)*MaxSrc);
  261. SourceCnt := 0;
  262. CalcVer := true;
  263. RealizSteps := 100;
  264. Buffer := aBuf;
  265. Device := aDev;
  266. Delta := aDel;
  267. DovInt := aDov;
  268. Reset;
  269. end;{CModel.Init}
  270. {---------------------------------------------------------}
  271. Procedure CModel.Reset;
  272. begin
  273. NextSource:=0;
  274. CurTime := 0;
  275. CurStep := 0;
  276. DoneCount := 0;
  277. RefusedCount := 0;
  278. RealizSteps := 100;
  279. TotalCount := 0;
  280. Working := false;
  281. end;{CModel.Reset}
  282. {------------------------------------------------------------------}
  283. Function CModel.SetSourceCount(aNewCnt:integer):boolean;
  284. var
  285. NewBuf : PSourceArr;
  286. Begin
  287. SetSourceCount := false;
  288. if aNewCnt > MaxSrc then
  289. begin
  290. GetMem(NewBuf,Sizeof(PSource)*aNewCnt);
  291. Move(Sources^,NewBuf^,Sizeof(PSource)*MaxSrc);
  292. FreeMem(Sources,Sizeof(PSource)*MaxSrc);
  293. Sources := NewBuf;
  294. MaxSrc := aNewCnt;
  295. SetSourceCount := true;
  296. end;
  297. end;{CModel.SetSourceCount}
  298. {------------------------------------------------------------------}
  299. Function CModel.AddNewSource(aNewSrc:PSource):boolean;
  300. Begin
  301. if SourceCnt >= MaxSrc then AddNewSource := SetSourceCount(MaxSrc+1);
  302. Sources^[SourceCnt] := aNewSrc;
  303. Inc(SourceCnt);
  304. end;{CModel.AddNewSource}
  305. {------------------------------------------------------------------}
  306. Function CModel.RemoveSource(aName:integer):boolean;
  307. var
  308. c : integer;
  309. Begin
  310. RemoveSource := false;
  311. if SourceCnt = 1 then exit;
  312. for c := 0 to SourceCnt-1 do if Sources^[c]^.Name = aName then break;
  313. if c = SourceCnt-1 then exit;
  314. Dispose(Sources^[c],Done);
  315. while c <> SourceCnt-1 do
  316. begin
  317. Sources^[c] := Sources^[c+1];
  318. inc(c);
  319. end;
  320. Dec(SourceCnt);
  321. end;{CModel.RemoveSource}
  322. {------------------------------------------------------------------}
  323. Procedure CModel.SetNextSource; {Находит NextSource}
  324. var
  325. c : integer;
  326. begin
  327. NextSource := 0;
  328. for c := 0 to SourceCnt-1 do
  329. begin
  330. if (Sources^[c]^.NewTime < Sources^[NextSource]^.NewTime) then
  331. NextSource := c;
  332. end;
  333. end;{CModel.SetNextSource}
  334. {------------------------------------------------------------------}
  335. Procedure CModel.Start;
  336. var
  337. c,First : integer;
  338. begin
  339. if (Device=nil) or (Buffer=nil) or (SourceCnt=0) then exit;
  340. Reset;
  341. Device^.Reset;
  342. Buffer^.FreeBuffer;
  343. First := 0;
  344. for c := 0 to SourceCnt-1 do
  345. begin
  346. Sources^[c]^.Reset;
  347. Sources^[c]^.GenNewReq;
  348. if (Sources^[c]^.NewTime < Sources^[First]^.NewTime) then
  349. First := c;
  350. end;
  351. WorkReq := Sources^[First]^.LastReq;
  352. Device^.AddReq(@WorkReq,Sources^[First]^.NewTime);
  353. Sources^[First]^.GenNewReq;
  354. SetNextSource;
  355. Working := true;
  356. end;
  357. {------------------------------------------------------------------}
  358. Function CModel.TestVer:boolean;
  359. var
  360. NewV,c,p:real;
  361. i : integer;
  362. begin
  363. NewV:=0;
  364. TestVer:=true;
  365. for i := 0 to SourceCnt-1 do if Sources^[i]^.RefusedReq <> 0 then
  366. begin
  367. p := 1.0 * Sources^[i]^.RefusedReq / Sources^[i]^.TotalReq;
  368. c := (DovInt*(1-p))/(Delta*Delta*p);
  369. if c > NewV then NewV := c;
  370. end;
  371. if NewV > RealizSteps then
  372. begin
  373. RealizSteps := round(NewV);
  374. TestVer := false;
  375. end;
  376. end;{CModel.TextVer}
  377. {------------------------------------------------------------------}
  378. Function CModel.Step:boolean;
  379. var
  380. Kicked : TReq;
  381. i : integer;
  382. ret : boolean;
  383. Begin
  384. Step := false;
  385. if Not Working then exit;
  386. ret := false; {Считаем, что продолжать не будем}
  387. if (not CalcVer) AND (CurStep > RealizSteps) then exit;
  388. for i:=0 to SourceCnt-1 do if Sources^[i]^.TotalReq < RealizSteps then
  389. ret:=true;
  390. if (not ret) AND CalcVer then ret := not TestVer;
  391. if Device^.DoneTime < Sources^[NextSource]^.NewTime then
  392. begin
  393. CurTime := Device^.DoneTime;
  394. WorkReq := Device^.DoneWork^;
  395. inc(DoneCount);
  396. inc(TotalCount);
  397. inc(WorkReq.FromSource^.DoneReq);
  398. WorkReq.FromSource^.WaitTime := WorkReq.FromSource^.WaitTime +
  399. WorkReq.Death - WorkReq.Birth;
  400. if Buffer^.GetReq(WorkReq) then
  401. begin {В буфере находилась заявка}
  402. WorkReq.FromSource^.MatWait := WorkReq.FromSource^.MatWait +
  403. CurTime-WorkReq.Birth;
  404. Device^.AddReq(@WorkReq,CurTime);
  405. end
  406. else {Need to gen new req}
  407. begin
  408. Device^.AddReq(@Sources^[NextSource]^.LastReq,Sources^[NextSource]^.LastReq.Birth);
  409. Sources^[NextSource]^.GenNewReq;
  410. SetNextSource;
  411. end;
  412. end
  413. else {Ближайшее событие - генерация запроса}
  414. begin
  415. CurTime := Sources^[NextSource]^.NewTime;
  416. if not Buffer^.AddReq(Sources^[NextSource]^.LastReq,Kicked) then
  417. begin
  418. inc(Kicked.FromSource^.RefusedReq);
  419. {Kicked.FromSource^.WaitTime := Kicked.FromSource^.WaitTime +
  420. Kicked.Death-Kicked.Birth;}
  421. Inc(RefusedCount);
  422. Inc(TotalCount);
  423. end;
  424. Sources^[NextSource]^.GenNewReq;
  425. SetNextSource;
  426. end; {}
  427. inc(CurStep);
  428. Step := ret;
  429. end;{CModel.Step}
  430. {------------------------------------------------------------------}
  431. Procedure CModel.PrintValues(var F:Text);
  432. var
  433. i : integer;
  434. begin
  435. WriteLn(F,'Отн. точность - ',Delta*100:0:0,'%, дов. инт в кв. - ',DovInt:0:2);
  436. WriteLn(F,'Хар-ка потока прибора - ', Device^.Lambda:0:2);
  437. WriteLn(F,'Ист.|Всг заяв.|Отк заяв.|Вып заяв.|P отк. |Мат. ож | Общ. вр.');
  438. for i := 0 to SourceCnt-1 do with Sources^[i]^ do
  439. begin
  440. write(F,Name:4,' ',TotalReq:9,' ',RefusedReq:9,' ',DoneReq:9,' ',100.0*RefusedReq/TotalReq:6:2,'% ');
  441. if DoneReq <> 0 then Write(F,MatWait/DoneReq:8:3,' ') else Write(F,' --- ');
  442. WriteLN(F,WaitTime:0:2);
  443. end;
  444. WriteLn(F,'Коэффициент простоя прибора - ',100*Device^.Stoppage/CurTime:0:2,'%');
  445. WriteLN(F,'---')
  446. end;{CModel.PrintValues}
  447. {------------------------------------------------------------------}
  448. Destructor CModel.Done;
  449. var
  450. c : integer;
  451. Begin
  452. for c:= 0 to SourceCnt-1 do Dispose(Sources^[c],Done);
  453. FreeMem(Sources,Sizeof(PSource)*MaxSrc);
  454. end;{CModel.Done}
  455. {------------------------------------------------------------------}
  456. END. {EOF}