CORE.PAS 17 KB

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