⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rapp_final.c

📁 对两次互交流是不是符合rapp算法的模拟仿真
💻 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 + -