unit U_Base;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls, Spin, TeEngine, Series, ExtCtrls, TeeProcs,
Chart, Buttons, Math, BubbleCh;
CONST MaxN = 100;
MaxR = 100;
type
TBase = class(TForm)
GroupBox1: TGroupBox;
Label1: TLabel;
n: TSpinEdit;
tzSG: TStringGrid;
Button1: TButton;
zSG: TStringGrid;
GroupBox2: TGroupBox;
Label4: TLabel;
Label5: TLabel;
M_Label: TLabel;
D_Label: TLabel;
Chart1: TChart;
Series1: TBarSeries;
Label6: TLabel;
Label7: TLabel;
Memo1: TMemo;
Memo2: TMemo;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
SpeedButton3: TSpeedButton;
Erlang_Label: TLabel;
Label3: TLabel;
FkStepEdit: TEdit;
Chart2: TChart;
Series2: TLineSeries;
Label10: TLabel;
GraphMinEdit: TEdit;
Label11: TLabel;
GraphMaxEdit: TEdit;
Chart3: TChart;
LineSeries1: TLineSeries;
Label2: TLabel;
IntegralEdit: TEdit;
Series3: TLineSeries;
Series4: TLineSeries;
Panel1: TPanel;
x2Label: TLabel;
GroupBox3: TGroupBox;
Label8: TLabel;
Edit1: TEdit;
Label9: TLabel;
Edit2: TEdit;
Label12: TLabel;
Edit3: TEdit;
Label13: TLabel;
Label14: TLabel;
Label15: TLabel;
Edit5: TEdit;
Label16: TLabel;
Edit6: TEdit;
Label17: TLabel;
Label18: TLabel;
Edit4: TEdit;
Label19: TLabel;
Edit7: TEdit;
Label20: TLabel;
Label21: TLabel;
Bevel1: TBevel;
Bevel2: TBevel;
Label22: TLabel;
Edit8: TEdit;
Button2: TButton;
Button3: TButton;
Label23: TLabel;
Label24: TLabel;
Label25: TLabel;
Label27: TLabel;
Label26: TLabel;
Label28: TLabel;
Label29: TLabel;
Label30: TLabel;
Label31: TLabel;
Label32: TLabel;
Label33: TLabel;
Label34: TLabel;
Label35: TLabel;
Label36: TLabel;
Label37: TLabel;
Label38: TLabel;
Label39: TLabel;
Edit9: TEdit;
Label40: TLabel;
Edit10: TEdit;
MoveCheck: TCheckBox;
Label41: TLabel;
Edit11: TEdit;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure nChange(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
procedure RandomTz;
procedure Calculate;
procedure ReDraw;
procedure ReDrawResults;
function Factorial(Argument:Integer):Extended;
function ErlangF(Order: integer; Argument:Real): Extended;
function ErlangFNorm(Order: integer; Argument:Real): Extended;
function ErlangIntegral(a,b: Real; Step:Real): Extended;
function ErlangIntegralNorm(a,b: Real; Step:Real): Extended;
function Erlang1stF(Argument:Real):Real;
function Erlang1stFNorm(Argument:Real):Real;
function ErlangRandom(Lambda:Real; Order: integer):Real;
procedure Modeling;
//procedure Simulate;
end;
var
Base: TBase;
Tz: array [1..MaxN] of real; // моменты поступления заявок
z: array [1..MaxN-1] of real; // интервалы
Kz: array [1..MaxN-1] of integer;// Интервалы гистограммы
k: integer;
m,d,klen, zmin, zmax: real; // Мат ож., Дисперсия, пар-ры гистограммы
Intensivity: real; // Интенсивность
StreamOrder: integer; // Порядок потока
FkStep, GraphMin, GraphMax: real; // Пар-ры графиков
IntegralStep: real; // Шаг интегрирования
X2: real; // Параметр ХИ-2 распределения
SimulationStep: real; // Шаг симуляции
SimulateON: boolean; // Включение симуляции
MaxAppearedQrLen: integer; // Макс. появившаяся длина очереди
QrCnt1: array [1..MaxR] of integer; // Кол-во пришедших заявок
QrCnt2: array [1..MaxR] of integer;
QrServCnt1: array [1..MaxR] of integer; // Кол-во обслуженных заявок
QrServCnt2: array [1..MaxR] of integer;
QrServTime1: array [1..MaxR] of real; // Общее время обслуживания заявок
QrServTime2: array [1..MaxR] of real;
QrRejbyWaitCnt1: array [1..MaxR] of integer; // Кол-во отказов из-за ожидания
QrRejbyWaitCnt2: array [1..MaxR] of integer;
QrRejbyMaxLCnt1: array [1..MaxR] of integer; // Кол-во отказов из-за забитости очереди
QrRejbyMaxLCnt2: array [1..MaxR] of integer;
QrWaitTime1: array [1..MaxR] of real; // Общее время ожидания обслуживания
QrWaitTime2: array [1..MaxR] of real;
Sr_QrCnt1, Sr_QrCnt2: integer; // Усредненные величины
Sr_QrServCnt1, Sr_QrServCnt2: integer;
Sr_QRServTime1, Sr_QrServTime2: real;
Sr_QrRejbyWaitCnt1, Sr_QrRejbyWaitCnt2: integer;
Sr_QrRejbyMaxLCnt1, Sr_QrRejbyMaxLCnt2: integer;
Sr_QrWaitTime1, Sr_QrWaitTime2: real;
State_NewQueryToLine1: boolean; // Флаг "Новая заявка --> Линия 1"
State_NewQueryToLine2: boolean; // Флаг "Новая заявка --> Линия 2"
State_NewQueryReject: boolean; // Флаг "Новая заявка --> отказ"
State_NewQueryToQr: boolean; // Флаг "Новая заявка --> очередь"
State_FromQrReject: boolean; // Флаг "Из очереди --> отказ"
State_FromQrToLine1: boolean; // Флаг "Из очереди --> Линия 1"
State_FromQrToLine2: boolean; // Флаг "Из очереди --> Линия 1"
function FloatToStr(x: real): string;
implementation
uses U_Simulate;
{$R *.dfm}
function FloatToStr(x: real): string;
var q: integer;
begin
result:=SysUtils.FloatToStr(x);
q:=POS(',',result);
If q<>0 then
begin
Delete(result,q,1);
Insert('.',result,q);
end;
if length(result)>q+3 then SetLength(result,q+3);
end;
procedure TBase.FormCreate(Sender: TObject);
begin
n.Value:=50;
StreamOrder:=0;
Randomize;
RandomTz;
ReDraw;
end;
procedure TBase.RandomTz;
var q: integer;
begin
Tz[1]:=0;
for q:=2 to n.Value do Tz[q]:=Tz[q-1]+Random(100)/10+1;
end;
function TBase.Factorial(Argument:Integer):Extended;
var q: integer;
begin
Result:=1;
For q:=2 to Argument do Result:=Result*q;
end;
// Функция распределения для потока Эрланга k-го порядка
function TBase.ErlangF(Order: integer; Argument:Real): Extended;
var TempParam,Value:Extended;
begin
TempParam:=Intensivity{*(Order+1)};
Result:=TempParam*Power(TempParam*Argument,Order)*Exp(-TempParam*Argument);
Result:=Result/Factorial(Order);
end;
// Нормированная Функция распределения для потока Эрланга k-го порядка
function TBase.ErlangFNorm(Order: integer; Argument:Real): Extended;
var TempParam,Value:Extended;
begin
TempParam:=Intensivity*(Order+1);
Result:=TempParam*Power(TempParam*Argument,Order)*Exp(-TempParam*Argument);
Result:=Result/Factorial(Order);
end;
// Расчет интеграла по функции распределения Эрланга
function TBase.ErlangIntegral(a,b: Real; Step:Real): Extended;
var sum,x: real;
begin
sum:=0;
x:=a;
While x<=b do
begin
sum:=sum+(Step * ErlangF(StreamOrder, x+Step/2));
x:=x+Step;
end;
result:=sum;
end;
// Расчет интеграла по нормированной функции распределения Эрланга
function TBase.ErlangIntegralNorm(a,b: Real; Step:Real): Extended;
var sum,x: real;
begin
sum:=0;
x:=a;
While x<=b do
begin
sum:=sum+(Step * ErlangFNorm(StreamOrder, x+Step/2));
x:=x+Step;
end;
result:=sum;
end;
// 1st interval
function TBase.Erlang1stF(Argument:Real):Real;
begin
Result:=Intensivity*(1-ErlangIntegral(0,Argument,IntegralStep));
end;
function TBase.Erlang1stFNorm(Argument:Real):Real;
begin
Result:=Intensivity*(StreamOrder+1)*(1-ErlangIntegralNorm(0,Argument,IntegralStep));
end;
// Случайный поток Эрланга k-го порадка
function TBase.ErlangRandom(Lambda:Real; Order: integer):Real;
var
R:Real;
q: integer;
begin
Result:=0;
For q:=0 to Order do Result:=Result + (-Lambda)*Ln(Random);
end;
////////////////////////////////////////////////////////////////////////////////
procedure TBase.Calculate;
var q, err, sum, w: integer;
begin
// Mean
m:=0; For q:=1 to n.Value-1 do m:=m+z[q]; m:=m/(n.Value-1);
// Variance
d:=0; For q:=1 to n.Value-1 do d:=d+SQR(z[q]-m); d:=d/(n.Value-1);
// Gistogramm
zmin:=z[1]; For q:=2 to n.Value-1 do if zmin>z[q] then zmin:=z[q];
zmax:=z[1]; For q:=2 to n.Value-1 do if zmax<z[q] then zmax:=z[q]; zmax:=zmax+0.01;
k:= TRUNC(1 + 3 * LN(n.Value)); klen:=(zmax-zmin)/k;
// Intensivity
intensivity:=1/m;
// StreamOrder
StreamOrder:=Round(1/(d*Sqr(Intensivity)) {-1});
If StreamOrder<0 then StreamOrder:=0;
// Get FkStep
VAL(FkStepEdit.Text,FkStep,err); if err<>0 then FkStep:=0.1;
VAL(GraphMinEdit.Text,GraphMin,err); if err<>0 then GraphMin:=0;
VAL(GraphMaxEdit.Text,GraphMax,err); if err<>0 then GraphMax:=100;
VAL(IntegralEdit.Text,IntegralStep,err); if err<>0 then IntegralStep:=0.1;
// X2 - check
X2:=0;
for q:=1 to k do
begin
sum:=0;
for w:=1 to n.Value-1 do
if (z[w]>=(q-1)*klen + zmin) AND (z[w]<(q)*klen + zmin) then INC(sum);
Kz[q]:=sum;
X2:=X2 + SQR(sum - (N.Value-1)*ErlangF(StreamOrder,(q-0.5)*klen + zmin)) /
(N.Value-1)*ErlangF(StreamOrder,(q-0.5)*klen + zmin);
end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure TBase.ReDraw;
var q: integer;
begin
If n.Text='' then exit;
For q:=1 to n.Value-1 do z[q]:=tz[q+1]-tz[q];
tzSG.RowCount:=n.Value;
for q:=1 to n.Value do
begin
tzSG.Cells[0,q-1]:=IntToStr(q);
tzSG.Cells[1,q-1]:=FloatToStr(Tz[q]);
end;
zSG.RowCount:=n.Value-1;
for q:=1 to n.Value-1 do
begin
zSG.Cells[0,q-1]:=IntToStr(q)+' - '+IntToStr(q+1);
zSG.Cells[1,q-1]:=FloatToStr(z[q]);
end;
{Chart4.Series[0].AddValue (1);
Chart4.Series[0].AddValue (4);
Chart4.Series[0].AddValue (8);
Chart4.Series[0].AddValue (2);
}
end;
procedure TBase.ReDrawResults;
var q, w: integer;
begin
M_Label.Caption:=FloatToStr(m);
D_Label.Caption:=FloatToStr(d);
// Gistogramm
Chart1.Series[0].Clear;
Label6.Caption:=FloatToStr(zmin);
Label7.Caption:=FloatToStr(zmax);
for q:=1 to k do
begin
Chart1.Series[0].AddXY (q, Kz[q]/(n.Value-1));
end;
Erlang_Label.Caption:='Порядок потока Эрланга ' + IntToStr(StreamOrder);
X2Label.Caption:='x2 ' + FloatToStr(X2);
// Erlang
Chart2.Series[0].Clear;
Chart2.Series[1].Clear;
w:=Round((GraphMax-GraphMin)/FkStep);
for q:=0 to w do
begin
Chart2.Series[0].AddXY (GraphMin+q*FkStep, ErlangF(StreamOrder,GraphMin+q*FkStep));
Chart2.Series[1].AddXY (GraphMin+q*FkStep, ErlangFNorm(StreamOrder,GraphMin+q*FkStep));
end;
// Erlang 1st interval
Chart3.Series[0].Clear;
Chart3.Series[1].Clear;
for q:=0 to w do
begin
Chart3.Series[0].AddXY (GraphMin+q*FkStep, Erlang1stF(GraphMin+q*FkStep));
Chart3.Series[1].AddXY (GraphMin+q*FkStep, Erlang1stFNorm(GraphMin+q*FkStep));
end;
end;
procedure TBase.Button1Click(Sender: TObject);
begin
ReDraw;
Calculate;
ReDrawResults;
end;
procedure TBase.nChange(Sender: TObject);
begin
ReDraw;
end;
procedure TBase.SpeedButton3Click(Sender: TObject);
begin
RandomTz;
ReDRaw;
end;
////////////////////////////////////////////////////////////////////////////////
procedure TBase.Modeling;
var w,err: integer;
QType: byte; // Тип поступившей заявки
CurT, nextT: real; // Текущее время и время прибытия следующей заявки
NextStateT, dt: real; // Время следующего состояния, dt
temptime: real;
temptype: byte;
CurStream: integer;
CurSrTime: real;
Qr: array of real; // Очередь (время)
QrType: array of byte; // Очередь (Тип заявки)
Line1Free, Line2Free: boolean; // Флаги свободы линий
Line1TimeOut, Line2TimeOut: real; // Время освобождения линии
Line1QType, Line2QType: byte; // Тип заявок в линиях
QrWaitExpires: real; // Время отказа заявки в очереди
MaxQrT1, MaxQrT2: real; // Макс. время нахождения заявки в очереди
RN: integer; // Кол-во реализаций
RCur: integer; // Текущая реализация
RT: real; // Длительность реализации
MaxQrLen: integer; // Макс. длина очереди
I1, I2: real; // Интенсивности обработки заявок
I1Time, I2Time: real; // Соответственно, время обработки заявок
FromQrRejN: integer;
mainstep: integer;
////////////////////////////////////////////////////////////////////////////
// С И М У Л Я Ц И Я
PROCEDURE Simulate;
VAR q: integer;
col: byte;
temptime, tempmax: real;
w1,w2: integer;
rcsize, rcx, rcy, rctext, rcrow: integer;
tx,ty, txstep, tystep: real;
rccolor: TColor;
begin
rcsize:=25;
rcx:=40;
rcy:=40;
rctext:=15;
rcrow:=10;
//mainstep:=7000;
With SimulateForm.MI do
begin
If MoveCheck.Checked then
BEGIN
if State_NewQueryToLine1 then
begin
if QType=1 then rccolor:=RGB(250,0,0)
else rccolor:=RGB(0,250,0);
SimulateForm.DrawAnimation(300,300,90,260, mainstep, rcsize, rccolor);
end;
if State_NewQueryToLine2 then
begin
if QType=1 then rccolor:=RGB(250,0,0)
else rccolor:=RGB(0,250,0);
SimulateForm.DrawAnimation(300,300,210,260, mainstep, rcsize, rccolor);
end;
if State_NewQueryToQr then
begin
w1:=(Length(Qr)-1) mod rcrow;
w2:=(Length(Qr)-1) div rcrow;
if QType=1 then rccolor:=RGB(250,0,0)
else rccolor:=RGB(0,250,0);
SimulateForm.DrawAnimation(300,300,20+rcx*w1,40+rcy*w2, mainstep, rcsize, rccolor);
end;
if State_NewQueryReject then
begin
if QType=1 then rccolor:=RGB(250,0,0)
else rccolor:=RGB(0,250,0);
SimulateForm.DrawAnimation(300,300,500,300, mainstep, rcsize, rccolor);
end;
if State_FromQrReject then
begin
w1:=FromQrRejN mod rcrow;
w2:=FromQrRejN div rcrow;
if QType=1 then rccolor:=RGB(250,0,0)
else rccolor:=RGB(0,250,0);
SimulateForm.DrawAnimation(20+rcx*w1,40+rcy*w2,500,300, mainstep, rcsize, rccolor);
end;
if State_FromQrToLine1 then
begin
if QType=1 then rccolor:=RGB(250,0,0)
else rccolor:=RGB(0,250,0);
SimulateForm.DrawAnimation(20,40,90,260, mainstep, rcsize, rccolor);
end;
if State_FromQrToLine2 then
begin
if QType=1 then rccolor:=RGB(250,0,0)
else rccolor:=RGB(0,250,0);
SimulateForm.DrawAnimation(20,40,210,260, mainstep, rcsize, rccolor);
end;
END;
//
//
//
// отображаем очередь
For q:=0 to MaxQrLen-1 do
if q<Length(Qr) then
begin
w1:=q mod rcrow;
w2:=q div rcrow;
temptime:=CurT-Qr[q];
if QrType[q]=1 then tempmax:=MaxQrT1 else tempmax:=MaxQrT2;
col:=Round (150 * (1-temptime/tempmax))+100;
if QrType[q]=1 then Canvas.Brush.Color:=RGB(col,0,0)
else Canvas.Brush.Color:=RGB(0,col,0);
Canvas.Ellipse(20+rcx*w1,40+rcy*w2,20+rcx*w1+ rcsize,40+rcy*w2+ rcsize);
Canvas.Brush.Color:=clBtnFace;
Canvas.TextOut(20+rcx*w1,40+rcy*w2-rctext,FloatToStr(tempmax-temptime));
end
else
begin
w1:=q mod rcrow;
w2:=q div rcrow;
Canvas.Brush.Color:=0;
Canvas.Ellipse(20+rcx*w1,40+rcy*w2,20+rcx*w1+ rcsize,40+rcy*w2+ rcsize);
Canvas.Brush.Color:=clBtnFace;
Canvas.TextOut(20+rcx*w1,40+rcy*w2-rctext,' ');
end;
// отображаени обработчик 1
if Line1Free then
begin
Canvas.Brush.Color:=0;
Canvas.Ellipse(50,220,130,300);
Canvas.Brush.Color:=clBtnFace;
Canvas.TextOut(50,200,' ');
end
else
begin
temptime:=Line1TimeOut-CurT;
if Line1QType=1 then tempmax:=I1Time else tempmax:=I2Time;
col:=Round (150 * (1-temptime/tempmax))+100;
if Line1QType=1 then Canvas.Brush.Color:=RGB(col,0,0)
else Canvas.Brush.Color:=RGB(0,col,0);
Canvas.Ellipse(50,220,130,300);
Canvas.Brush.Color:=clBtnFace;
Canvas.TextOut(50,200,FloatToStr(temptime));
end;
// отображаени обработчик 2
if Line2Free then
begin
Canvas.Brush.Color:=0;
Canvas.Ellipse(170,220,250,300);
Canvas.Brush.Color:=clBtnFace;
Canvas.TextOut(170,200,' ');
end
else
begin
temptime:=Line2TimeOut-CurT;
if Line2QType=1 then tempmax:=I1Time else tempmax:=I2Time;
col:=Round (150 * (1-temptime/tempmax))+100;
if Line2QType=1 then Canvas.Brush.Color:=RGB(col,0,0)
else Canvas.Brush.Color:=RGB(0,col,0);
Canvas.Ellipse(170,220,250,300);
Canvas.Brush.Color:=clBtnFace;
Canvas.TextOut(170,200,FloatToStr(temptime));
end;
end;
SimulateForm.Label2.Caption:='Реализация '+ FloatToStr(RCur);
SimulateForm.Label1.Caption:='Время '+ FloatToStr(CurT);
WITH SimulateForm do
begin
Label23.Caption:='Количество пришедших заявок '+IntToStr(QrCnt1[RCur]+QrCnt2[RCur]);
Label24.Caption:='1ого рода '+IntToStr(QrCnt1[RCur]);
Label25.Caption:='2ого рода '+IntToStr(QrCnt2[RCur]);
Label27.Caption:='Макс. возникшая длина очереди '+IntToStr(MaxAppearedQrLen);
Label30.Caption:='Количество обслуженных заявок '+IntToStr(QrServCnt1[RCur]+QrServCnt2[RCur]);
Label28.Caption:='1ого рода '+IntToStr(QrServCnt1[RCur]);
Label29.Caption:='2ого рода '+IntToStr(QrServCnt2[RCur]);
Label26.Caption:='Общее время обслуживания заявок '+FloatToStr(QrServTime1[RCur]+QrServTime2[RCur]);
Label31.Caption:='1ого рода '+FloatToStr(QrServTime1[RCur]);
Label32.Caption:='2ого рода '+FloatToStr(QrServTime2[RCur]);
if (QrServCnt1[RCur]<>0) AND (QrServCnt2[RCur]<>0) then
begin
Label33.Caption:='Среднее время ожидания заявкой ' +
FloatToStr((QrWaitTime1[RCur]/QrServCnt1[RCur] + QrWaitTime2[RCur]/QrServCnt2[RCur]) /2);
Label34.Caption:='1ого рода '+FloatToStr(QrWaitTime1[RCur]/QrServCnt1[RCur]);
Label35.Caption:='2ого рода '+FloatToStr(QrWaitTime2[RCur]/QrServCnt2[RCur]);
end;
Label36.Caption:='Количество отказов (вс./оч.) '+
IntToStr(QrRejByMaxLCnt1[RCur] + QrRejByWaitCnt1[RCur] +
QrRejByMaxLCnt2[RCur] + QrRejByWaitCnt2[RCur]) +
' / '+IntToStr(QrRejByMaxLCnt1[RCur] + QrRejByMaxLCnt2[RCur]);
Label37.Caption:='1ого рода '+
IntToStr(QrRejByMaxLCnt1[RCur] + QrRejByWaitCnt1[RCur]) +
' / '+IntToStr(QrRejByMaxLCnt1[RCur]);
Label38.Caption:='2ого рода '+
IntToStr(QrRejByMaxLCnt2[RCur] + QrRejByWaitCnt2[RCur]) +
' / '+IntToStr(QrRejByMaxLCnt2[RCur]);
end;
Application.ProcessMessages;
end;
////////////////////////////////////////////////////////////////////////////
// Функция определения время отказа заяыки в очереди
function SingleQrWaitExpires(n: integer): real;
var q: integer;
begin
if QrType[n]=1 then result:=MaxQrT1+Qr[n]
else result:=MaxQrT2+Qr[n];
end;
// Процедура определения минимального времени выхода заяки из очереди
function GetQrTimeOut: real;
var q: integer;
min, temp: real;
begin
if Length(Qr)=0 then exit;
min:=SingleQrWaitExpires(0);
for q:=1 to Length(Qr)-1 do
begin
temp:=SingleQrWaitExpires(q);
if temp < min then min:=temp;
end;
QrWaitExpires:=min;
end;
// Процедура выхода заявки из очереди
function QueryGo(n: integer): byte;
var q: integer;
begin
result:=QrType[n];
for q:=n+1 to Length(Qr)-1 do
begin
Qr[q-1]:=Qr[q];
QrType[q-1]:=QrType[q];
end;
SetLength(Qr,Length(Qr)-1);
SetLength(QrType,Length(Qr));
end;
begin
// Считывание данных
VAL(Edit1.Text,RN,err); if err<>0 then exit; if RN>MaxR then RN:=MaxR;
VAL(Edit2.Text,RT,err); if err<>0 then exit;
VAL(Edit3.Text,MaxQrLen,err); if err<>0 then exit;
VAL(Edit5.Text,I1,err); if err<>0 then exit;
VAL(Edit6.Text,I2,err); if err<>0 then exit;
I1Time:=1/I1; Label20.Caption:='/ вр. '+FloatToStr(I1Time);
I2Time:=1/I2; Label21.Caption:='/ вр. '+FloatToStr(I2Time);
VAL(Edit4.Text,MaxQrT1,err); if err<>0 then exit;
VAL(Edit7.Text,MaxQrT2,err); if err<>0 then exit;
VAL(Edit8.Text,SimulationStep,err); if err<>0 then exit;
VAL(Edit9.Text,CurSrTime,err); if err<>0 then exit;
VAL(Edit10.Text,CurStream,err); if err<>0 then exit;
VAL(Edit11.Text,mainstep,err); if err<>0 then exit;
// Усредненные величины
Sr_QrCnt1:=0; Sr_QrCnt2:=0;
Sr_QrServCnt1:=0; Sr_QrServCnt2:=0;
Sr_QRServTime1:=0; Sr_QrServTime2:=0;
Sr_QrRejbyWaitCnt1:=0; Sr_QrRejbyWaitCnt2:=0;
Sr_QrRejbyMaxLCnt1:=0; Sr_QrRejbyMaxLCnt2:=0;
Sr_QrWaitTime1:=0; Sr_QrWaitTime2:=0;
MaxAppearedQrLen:=0;
// Начало цикла по всем реализациям
For RCur:=1 to RN do
BEGIN
// Сброс на начальное состояние
QrCnt1[RCur]:=0;
QrCnt2[RCur]:=0;
QrServCnt1[RCur]:=0;
QrServCnt2[RCur]:=0;
QrServTime1[RCur]:=0;
QrServTime2[RCur]:=0;
QrRejbyWaitCnt1[RCur]:=0;
QrRejbyWaitCnt2[RCur]:=0;
QrRejbyMaxLCnt1[RCur]:=0;
QrRejbyMaxLCnt2[RCur]:=0;
QrWaitTime1[RCur]:=0;
QrWaitTime2[RCur]:=0;
State_NewQueryToLine1:=false;
State_NewQueryToLine2:=false;
State_NewQueryReject:=false;
State_NewQueryToQr:=false;
State_FromQrReject:=false;
State_FromQrToLine1:=false;
State_FromQrToLine2:=false;
CurT:=0;
nextT:=ErlangRandom(CurSrTime,CurStream);
Line1Free:=true;
Line2Free:=true;
SetLength(Qr,0);
SetLength(QrType,0);
QrWaitExpires:=0;
Line1TimeOut:=0;
Line2TimeOut:=0;
While CurT < RT do
// Время пошло:)
begin
// ЛИНИЯ 1 ОСВОБОДИЛАСЬ
if (NOT Line1Free) AND (CurT >= Line1TimeOut) then
begin
// Увеличиваем кол-во и время обслуженных заявок
If Line1QType=1 then INC(QrServCnt1[RCur]) else INC(QrServCnt2[RCur]);
if Line1QType=1 then QrServTime1[RCur]:=QrServTime1[RCur]+I1Time
else QrServTime2[RCur]:=QrServTime2[RCur]+I2Time;
if Length(Qr)<>0 then
// Очередь не пуста, поэтому в линию поступает заявка из очереди
begin
temptime:=Qr[0];
QType:=QueryGo(0); // выпускаем заявку из очереди
GetQrTimeOut;
if QType=1 then Line1TimeOut:=CurT + I1Time
else Line1TimeOut:=CurT + I2Time;
Line1QType:=QType;
// Увеличиваем Время ожидания
if Line1QType=1 then QrWaitTime1[RCur]:=QrWaitTime1[RCur]+(CurT-temptime)
else QrWaitTime2[RCur]:=QrWaitTime2[RCur]+(CurT-temptime);
State_FromQrToLine1:=TRUE;
end else
// Очередь пуста
begin
Line1Free:=true;
end;
end;
// ЛИНИЯ 2 ОСВОБОДИЛАСЬ
if (NOT Line2Free) AND (CurT >= Line2TimeOut) then
begin
// Увеличиваем кол-во и время обслуженных заявок
If Line2QType=1 then INC(QrServCnt1[RCur]) else INC(QrServCnt2[RCur]);
if Line2QType=1 then QrServTime1[RCur]:=QrServTime1[RCur]+I1Time
else QrServTime2[RCur]:=QrServTime2[RCur]+I2Time;
if Length(Qr)<>0 then
// Очередь не пуста, поэтому в линию поступает заявка из очереди
begin
temptime:=Qr[0];
QType:=QueryGo(0); // выпускаем заявку из очереди
GetQrTimeOut;
if QType=1 then Line2TimeOut:=CurT + I1Time
else Line2TimeOut:=CurT + I2Time;
Line2QType:=QType;
// Увеличиваем Время ожидания
if Line2QType=1 then QrWaitTime1[RCur]:=QrWaitTime1[RCur]+(CurT-temptime)
else QrWaitTime2[RCur]:=QrWaitTime2[RCur]+(CurT-temptime);
State_FromQrToLine2:=TRUE;
end else
// Очередь пуста
begin
Line2Free:=true;
end;
end;
// ВРЕМЯ ПРОБЫВАНИЯ ЗАЯВКИ В ОЧЕРЕДИ ИСТЕКЛО
if (Length(Qr)>0) AND ((CurT >= QrWaitExpires)) then
begin
w:=0;
For w:=0 to Length(Qr)-1 do
if (CurT >= SingleQrWaitExpires(w)) then
begin
temptype:=QrType[w];
// Увеличиваем время отказа
if temptype=1 then INC(QrRejbyWaitCnt1[RCur]) else INC(QrRejbyWaitCnt2[RCur]);
QType:=QrType[w];
QueryGo(w);
State_FromQrReject:=TRUE;
FromQrRejN:=w;
break;
end;
GetQrTimeOut;
end;
// ПРИШЛА ЗАЯВКА
if CurT >= nextT then
begin
// Обработка поступившей заявки
QType:=RANDOM(2)+1; // Тип заявки
// Увеличиваем число поступивших заявок
If QType = 1 then INC(QrCnt1[RCur]) else INC(QrCnt2[RCur]);
If Line1Free then
// Линия 1 Свободна
begin
Line1Free:=false;
if QType=1 then Line1TimeOut:=CurT + I1Time
else Line1TimeOut:=CurT + I2Time;
Line1QType:=QType;
State_NewQueryToLine1:=TRUE;
end else
If Line2Free then
// Линия 2 Свободна
begin
Line2Free:=false;
if QType=1 then Line2TimeOut:=CurT + I1Time
else Line2TimeOut:=CurT + I2Time;
Line2QType:=QType;
State_NewQueryToLine2:=TRUE;
end else
// Обе линии заняты
begin
w:=Length(Qr);
if w=MaxQrLen then
// Очередь забита полностью - ОТКАЗ:(
begin
State_NewQueryReject:=TRUE;
// Увеличиваем число отказов из-за забитости очереди
If QType = 1 then INC(QrRejbyMaxLCnt1[RCur]) else INC(QrRejbyMaxLCnt2[RCur]);
end
// Помещаем заявку в очередь
else
begin
SetLength(Qr,w+1);
SetLength(QrType,w+1);
Qr[w]:=CurT;
QrType[w]:=QType;
If Length(Qr)>MaxAppearedQrLen then MaxAppearedQrLen:=Length(Qr);
State_NewQueryToQr:=TRUE;
GetQrTimeOut;
end;
end;
// Определение следующей заявки
nextT:=CurT+ErlangRandom(CurSrTime,CurStream);
end;
// Определяем шаг времени, чтобы попасть в следующее состояние системы
NextStateT:=NextT;
if Length(Qr)>0 then NextStateT:=MIN(NextStateT,QrWaitExpires);
if NOT Line1Free then NextStateT:=MIN(NextStateT,Line1TimeOut);
if NOT Line2Free then NextStateT:=MIN(NextStateT,Line2TimeOut);
if SimulateON then
begin
dt:=MIN(NextStateT-CurT, SimulationStep);
Simulate;
Application.ProcessMessages;
if SimulateForm.StopButton.Down then
begin
SimulateForm.StopButton.Down:=false;
SimulateForm.PauseButton.Down:=false;
SimulateForm.Close;
EXIT;
end;
Repeat Application.ProcessMessages; Until NOT SimulateForm.PauseButton.Down;
CurT:=CurT+dt;
end
else CurT:=NextStateT;
State_NewQueryToLine1:=false;
State_NewQueryToLine2:=false;
State_NewQueryReject:=false;
State_NewQueryToQr:=false;
State_FromQrReject:=false;
State_FromQrToLine1:=false;
State_FromQrToLine2:=false;
end;
END;
////////////////////////////////////////////////////////////////////////////
// Подсчет средних значений
For RCur:=1 to RN do
begin
Sr_QrCnt1:=Sr_QrCnt1+ QrCnt1[RCur];
Sr_QrCnt2:=Sr_QrCnt2+ QrCnt2[RCur];
Sr_QrServCnt1:=Sr_QrServCnt1+ QrServCnt1[RCur];
Sr_QrServCnt2:=Sr_QrServCnt2+ QrServCnt2[RCur];
Sr_QRServTime1:=Sr_QRServTime1+ QRServTime1[RCur];
Sr_QrServTime2:=Sr_QRServTime2+ QRServTime2[RCur];
Sr_QrRejbyWaitCnt1:=Sr_QrRejbyWaitCnt1+ QrRejbyWaitCnt1[RCur];
Sr_QrRejbyWaitCnt2:=Sr_QrRejbyWaitCnt2+ QrRejbyWaitCnt2[RCur];
Sr_QrRejbyMaxLCnt1:=Sr_QrRejbyMaxLCnt1+ QrRejbyMaxLCnt1[RCur];
Sr_QrRejbyMaxLCnt2:=Sr_QrRejbyMaxLCnt2+ QrRejbyMaxLCnt2[RCur];
Sr_QrWaitTime1:=Sr_QrWaitTime1+ QrWaitTime1[RCur];
Sr_QrWaitTime2:=Sr_QrWaitTime2+ QrWaitTime2[RCur];
end;
Sr_QrCnt1:=Sr_QrCnt1 div RN;
Sr_QrCnt2:=Sr_QrCnt2 div RN;
Sr_QrServCnt1:=Sr_QrServCnt1 div RN;
Sr_QrServCnt2:=Sr_QrServCnt2 div RN;
Sr_QRServTime1:=Sr_QRServTime1 /RN;
Sr_QrServTime2:=Sr_QRServTime2 /RN;
Sr_QrRejbyWaitCnt1:=Sr_QrRejbyWaitCnt1 div RN;
Sr_QrRejbyWaitCnt2:=Sr_QrRejbyWaitCnt2 div RN;
Sr_QrRejbyMaxLCnt1:=Sr_QrRejbyMaxLCnt1 div RN;
Sr_QrRejbyMaxLCnt2:=Sr_QrRejbyMaxLCnt2 div RN;
Sr_QrWaitTime1:=Sr_QrWaitTime1 /RN;
Sr_QrWaitTime2:=Sr_QrWaitTime2 /RN;
Label23.Caption:='Количество пришедших заявок '+IntToStr(Sr_QrCnt1+Sr_QrCnt2);
Label24.Caption:='1ого рода '+IntToStr(Sr_QrCnt1);
Label25.Caption:='2ого рода '+IntToStr(Sr_QrCnt2);
Label27.Caption:='Макс. возникшая длина очереди '+IntToStr(MaxAppearedQrLen);
Label30.Caption:='Количество обслуженных заявок '+IntToStr(Sr_QrServCnt1+Sr_QrServCnt2);
Label28.Caption:='1ого рода '+IntToStr(Sr_QrServCnt1);
Label29.Caption:='2ого рода '+IntToStr(Sr_QrServCnt2);
Label26.Caption:='Общее время обслуживания заявок '+FloatToStr(Sr_QrServTime1+Sr_QrServTime2);
Label31.Caption:='1ого рода '+FloatToStr(Sr_QrServTime1);
Label32.Caption:='2ого рода '+FloatToStr(Sr_QrServTime2);
if (Sr_QrServCnt1<>0) AND (Sr_QrServCnt2<>0) then
begin
Label33.Caption:='Среднее время ожидания заявкой ' +
FloatToStr((Sr_QrWaitTime1/Sr_QrServCnt1 + Sr_QrWaitTime2/Sr_QrServCnt2) /2);
Label34.Caption:='1ого рода '+FloatToStr(Sr_QrWaitTime1/Sr_QrServCnt1);
Label35.Caption:='2ого рода '+FloatToStr(Sr_QrWaitTime2/Sr_QrServCnt2);
end;
Label36.Caption:='Количество отказов (вс./оч.) '+
IntToStr(Sr_QrRejByMaxLCnt1 + Sr_QrRejByWaitCnt1 +
Sr_QrRejByMaxLCnt2 + Sr_QrRejByWaitCnt2) +
' / '+IntToStr(Sr_QrRejByMaxLCnt1 + Sr_QrRejByMaxLCnt2);
Label37.Caption:='1ого рода '+
IntToStr(Sr_QrRejByMaxLCnt1 + Sr_QrRejByWaitCnt1) +
' / '+IntToStr(Sr_QrRejByMaxLCnt1);
Label38.Caption:='2ого рода '+
IntToStr(Sr_QrRejByMaxLCnt2 + Sr_QrRejByWaitCnt2) +
' / '+IntToStr(Sr_QrRejByMaxLCnt2);
end;
procedure TBase.Button2Click(Sender: TObject);
begin
SimulateON:=true;
SimulateForm.Show;
Modeling;
end;
procedure TBase.Button3Click(Sender: TObject);
begin
SimulateON:=false;
Modeling;
end;
end.