📄 rapp_final.c
字号:
/*计算机模拟rapp算法*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <malloc.h>
#include <stdlib.h>
#define alpha 120 //定义平均服务时间的参数
#define NN 20000 //定义通往每个路由的呼叫量
float *call1,*call2,*call3,*win1,*win2,*win3; //call为每个路由器到达的呼叫数,win为每个路由器有的中继线数目
int len[11]={0}; //len为第三个路由器溢出的呼叫数目
//迭代算法计算ErlangB
float erlangb(int s,float a)
{
float erB=0;
if (s==1) erB= (float) (a/(1.00+a));
else erB=1.0-s/(s+erlangb(s-1,a)*a);
return erB;
}
//溢出呼叫量方差的计算
float varfof(int s,float a )
{ float var,mea;
mea=a*erlangb(s,a);
var=mea*(1-mea+a/(s+1+mea-a));
return var;
}
//rapp算法计算出等效的呼叫量
float rappa(float mea ,float var)
{
float a,z;
int s;
z=var/mea;
a=var+3*z*(z-1);
s=(int) (a*(mea+z)/(mea+z+1)-mea-1);
a=(s+mea+1)*(mea+z+1)/(mea+z);
return a;
}
//rapp算法计算出等效的中继线数目
int rapps(float mea ,float var)
{
float a,z;
int s;
z=var/mea;
a=var+3*z/(z-1);
s=(int) (a*(mea+z)/(mea+z+1)-mea-1);
return s;
}
//均匀分布函数
double uniform()
{
double k=0;
double t;
while(k==0)
k=rand();
t=k/RAND_MAX;
return (t);
}
//负指数分布函数
float exponent(float b)
{
float u;
double x;
u=uniform();
x=-b*log(u);
return x;
}
//呼叫初始化函数
void Initiate(float *cl,int cnum,float beta)
{
int i;
long int s;
float intern=0; //设置时间间隔
srand(time(NULL)); //把当前时间设为随机数种子
for(i=0;i<cnum;i++) //用cl[]表示呼叫流到达的时间
{
cl[i]=exponent(beta);
cl[i]+=intern;
intern=cl[i];
}
}
//起泡法队列排序,按照呼叫前后的时间对呼叫从小到大重新排序
float* refresh(float *queue,int maxlong)
{
int i,j;
float t;
for(i=1;i<=maxlong-1;i++)
{
for(j=1;j<=maxlong-i;j++)
if(queue[j]>queue[j+1])
{
t=queue[j];
queue[j]=queue[j+1];
queue[j+1]=t;
}
}
return(queue);
}
//模拟一个路由器的mms即时拒绝系统,并且把溢出的呼叫流合并到下一个路由器的呼叫流中
//并完成按照呼叫流到达的时间排序
void mms(float *calla,float *callb,float *S ,int sanum,int pos) //calla,callb分别为到两个路由器的呼叫时间数列
{ //sanum,为第一个路由器的中继线数目
int i,j;
for (j=0;j<sanum;j++) S[j]=0; //对中继线状态初始化,S[]记录中继线繁忙的时间
for (i=0;i<NN;i++) //开始分析每一个到达a路由的呼叫
{
for (j=0;j<sanum;j++) //对每一个呼叫流开始遍历中继线
{
if (calla[i]>S[j]) //找到一条中继线如果呼叫到达的时间〉中继线繁忙的时间,则表示此中继线可以占用
{
S[j]=calla[i]+exponent(alpha);//此中继线的繁忙时间=到达的呼叫时间+将要占用的服务时间
break; //呼叫找到可用中继线,转到下一个到来的呼叫
}
}
if (j==sanum){callb[pos++]=calla[i];} //遍历所有中继线没有找到可用的(j=sanum)
} //此时的队列为溢出的队列calla[i],加入到下一个路由器的呼叫队列中
callb=refresh(callb,pos); //对通到下一个路有器的呼叫重新排序
}
//分析第三个路由最终溢出的呼叫数
void mms2(float *calla,float *S ,int sanum,int t,int pos) //calla为到路由器的呼叫时间数列,t设置时间间隔
{ //sanum为第一个路由器的中继线数目,pos统计溢出数量
int i,j;
for (j=0;j<sanum;j++) S[j]=0; //对中继线状态初始化,S[]记录中继线繁忙的时间
for (i=0;i<NN;i++) //开始分析每一个到达a路由的呼叫
{
for (j=0;j<sanum;j++) //对每一个呼叫流开始遍历中继线
{
if (calla[i]>S[j]) //找到一条中继线如果呼叫到达的时间〉中继线繁忙的时间,则表示此中继线可以占用
{
S[j]=calla[i]+exponent(alpha);//此中继线的繁忙时间=到达的呼叫时间+将要占用的服务时间
break; //呼叫找到可用中继线,转到下一个到来的呼叫
}
}
if (j==sanum){pos++;} //遍历所有中继线没有找到可用的(j=sanum)
if (t<=10 && (calla[i]<5000*t)&&(calla[i+1]>=5000*t))
{ len[t]=pos;t++;} //统计时间段内的溢出呼叫数
}
}
//统计在时间5000*t内每个路由器通过了多少呼叫量
int num(int t ,float *call)
{
int i,cnum;
for (i=1;i<=NN;i++)
{
if ((call[i]<5000*t)&&(call[i+1]>=5000*t))
{
cnum=i;
break;
}
}
return cnum;
}
int main(void)
{
int i,snum1,snum2,snum3,cnum1[11],cnum2[11],cnum3[11],cnum[11];
float a,b,c,yichu,arrate1,arrate2,arrate3,fof1a,fof2a,fof3a,fof1v,fof2v,fof3v;
//输入到达poisson流的到达率
printf("请输入到第一个路由的第一个呼叫流的平均到达间隔时间="); scanf("%f",&arrate1);
printf("请输入到第二个路由的第一个呼叫流的平均到达间隔时间="); scanf("%f",&arrate2);
printf("请输入到第三个路由的第一个呼叫流的平均到达间隔时间="); scanf("%f",&arrate3);
//输入路由器中继线数目的信息
printf("请输入路由器1的窗口数目="); scanf("%d",&snum1);
printf("请输入路由器2的窗口数目="); scanf("%d",&snum2);
printf("请输入路由器3的窗口数目="); scanf("%d",&snum3);
//对到达每个路由器的呼叫数队列,最后的溢出数列分配大小
//对每个中继线数列分配大小
call1=malloc(sizeof(float)*NN);
call2=malloc(sizeof(float)*2*NN);
call3=malloc(sizeof(float)*3*NN);
win1=malloc(sizeof(float)*snum1);
win2=malloc(sizeof(float)*snum2);
win3=malloc(sizeof(float)*snum3);
//分别对到达每个路由器的呼叫初始化,确定呼叫到来的时间
Initiate(call1,NN,arrate1);
Initiate(call2,NN,arrate2);
Initiate(call3,NN,arrate3);
//lem[i]计算每个时间段内的溢出呼叫,cnum[i]计算每个时间段内的呼叫总数
cnum1[0]=0;cnum2[0]=0;cnum3[0]=0;cnum[0]=0;len[0]=0;
for (i=1;i<=10;i++)
{
cnum1[i]=num(i,call1);//每个路由器时间段内的呼叫数
cnum2[i]=num(i,call2);
cnum3[i]=num(i,call3);
cnum[i]=cnum1[i]+cnum2[i]+cnum3[i];//三个路由器一共的呼叫数
}
//分析第一个路由器,溢出的呼叫合并到call2
mms(call1,call2,win1,snum1,NN);
//分析第二个路由器,溢出的呼叫合并到call3
mms(call2,call3,win2,snum2,NN);
//分析第三个路由器,返回溢出呼叫的数目
mms2(call3,win3,snum3,1,0);
//打印出每个时间段内的呼叫总数和溢出呼叫总数
for (i=1;i<=10;i++)
{
printf("在时间区间[%d-%d]内通过的呼叫数为%d,溢出呼叫量为%d\n",(i-1)*5000,i*5000,cnum[i]-cnum[i-1],len[i]-len[i-1]);
//rapp算法计算出呼损
a=alpha/arrate1;b=alpha/arrate2;c=alpha/arrate3;
fof1a=(float) a*erlangb(snum1,a)+b;
fof1v=(float) varfof(snum1,a)+b;//通过路由器1后的总呼叫量和方差
fof2a=(float) rappa(fof1a,fof1v)*erlangb(rapps(fof1a,fof1v)+snum2,rappa(fof1a,fof1v))+c;
fof2v=(float) varfof(rapps(fof1a,fof1v)+snum2,rappa(fof1a,fof1v))+c;//通过路由器2后的总呼叫量和方差
yichu=(float) rappa(fof2a,fof2v)*erlangb(rapps(fof2a,fof2v)+snum3,rappa(fof2a,fof2v));//计算最后的一处呼叫量
printf("最终由rapp算法计算出来的溢出呼叫量为%7.0f\n",5000/(yichu*alpha));
printf("\n");
}
//释放内存分配的空间
free(call1);free(call2);free(call3);free(win1);free(win2);free(win3);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -