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

📄 vrptwtest.cpp

📁 vrp问题的解决
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include<stdio.h>
#include<stdlib.h>
//#include<iostream.h>
#include<fstream.h>
#include<math.h>
#include<time.h>
//#include<cstdlib>
#include<iomanip.h> 
#include<assert.h>
//using namespace std;


#define CITY_NUM 9  //车场+任务数
#define MAX_ROUTE_LEN  16// 路径中的最多结点个数
#define ANT_NUM 8 //蚂蚁数量
//#define ANT_NUM 1 //蚂蚁数量
#define CONTENT 8.0  //车载容量
//#define CONTENT 100000.0  //车载容量

double w[9][9];//车载利用率
double u[9][9];//节省量
#define TIMES 5
ofstream outfile;
double atime1;
struct ROUTE
{ 
	int tour[MAX_ROUTE_LEN];
	double len;
	int carnum;
	int tflag;
};
struct SUB_ROUTE
{ 
	int tour[CITY_NUM];
	double partlen;
	double partsum;
	int cities;
};
struct NEEDPOINT
{
	double starttime;
	double endtime;
	int num;
} ordertime[CITY_NUM]; //该结构体是包含最晚时间和第几个城市即那一个城市的最晚时间
struct ROUTE *ant,bestant,testour;
double g[CITY_NUM]={0,2,1.5,4.5,3,1.5,4,2.5,3}; //各个城市的需求量
double D[CITY_NUM][CITY_NUM]={{0,40,60,75,90,200,100,160,80},{40,0,65,40,100,50,75,110,100},
{60,65,0,75,100,100,75,75,75},{75,40,75,0,100,50,90,90,150},{90,100,100,100,0,100,75,75,100},
{200,50,100,50,100,0,70,90,75},{100,75,75,90,75,70,0,70,100},{160,110,75,90,75,90,70,0,100},
{80,100,75,150,100,75,100,100,0}}; //各个城市之间的距离
double TW[CITY_NUM][2]={{0,0},{1,4},{4,6},{1,2},{4,7},{3,5},{2,5},{5,8},{1.5,4}};//各个城市点的开始时间和结束时间TW[CITY_NUM][0]是各个最早时间TW[CITY_NUM][1]是最迟到时间

//double TW[CITY_NUM][2]={{0,1000000},{0,1000000},{0,1000000},{0,1000000},{0,1000000},{0,1000000},{0,1000000},{0,1000000},{0,1000000}};//各个城市点的开始时间和结束时间TW[CITY_NUM][0]是各个最早时间TW[CITY_NUM][1]是最迟到时间
//设置时间窗为[0,1000000]很大则该问题就变成为不带时间窗的车辆调度问题即(VRP问题)

double T[CITY_NUM]={0,1,2,1,2,2,2.5,3,0.8};//各个点上的服务时间(可能包括卸货时间和工作人员休息时间等)
int tabu[CITY_NUM];
double tau[CITY_NUM][CITY_NUM],yita[CITY_NUM][CITY_NUM],detatau[CITY_NUM][CITY_NUM];
double max_len,min_need; 
double alpha,beta,rou,Q,tau0,q0;
double  maxtau,mintau,L;
int best_gen,best_num,gen;
clock_t start_time, finish_time;
int hflag=0;
double  duration; //测量一个事件持续的时间
//double dist(int i,int j);
void calc_dist();
double max_dist();
void initneed();
double calc_length(int *tour);
void init_tau_by_value(double value);
void init_uniform();
void clear_global_update();
void global_update_rule();
void init_tau_by_value(double value);
void init_uniform();
void clear_global_update();
void global_update_rule();
 
      

/*************************************
    求任务之间的距离矩阵
*************************************/
void calc_dist()
{   
	int i,j;
	int m=0;
	printf("各个任务之间的距离矩阵D[I][J]:");
	outfile<<"\n各个任务之间的距离矩阵D[I][J]:"<<endl;
    for (i=0;i<CITY_NUM;i++)
	{
		for (j=0;j<CITY_NUM;j++)
		{
			if (m%9==0) 
				printf("\n");
			
			outfile<<setw(5)<<D[i][j];
			printf("%7.1f", D[i][j]);
           	m++;
		}
		printf("\n");
		outfile<<"\n";
	}


   



}

 /**********************************
           产生各货场的需求量并找到最小的需求
 **********************************/
 void init_need()
 {
   int i,temp;
   min_need=g[1];
   printf("各个点的需求量g[i]为:");
   outfile<<"各个点的需求量g[i]为:\n";
   for (i=0;i<CITY_NUM;i++)
   {
	   if (i%9==0) printf("\n"); 
	   if ((i>0)&&(g[i]<min_need)) 
	   {
		   min_need=g[i];
           temp=i;
	   }
	   printf("%5.1f",g[i]);  
	   
   }
   printf("\n其中最小的需求量是第%d点,需求量是%f\n",temp,min_need);
   for(i=0;i<CITY_NUM;i++)
   {
	  outfile<<setw(8)<<g[i];
   }
   outfile<<"\n其中最小的需求量是第"<<temp<<"点,需求量是"<<min_need;

}

/**************************************
  按从小到大的顺序将各货场的关门时间排序
 **************************************/
 void order_endtime()
 {   
	 int i,j,k;
	 struct NEEDPOINT temp;
     for (k=0;k<CITY_NUM;k++)
	 {
		  ordertime[k].starttime=TW[k][0];
		ordertime[k].endtime=TW[k][1]; //TW[k][1]是第k个城市点的最晚时间
	   ordertime[k].num=k; //第k个城市
	    //double TW[CITY_NUM][2]={{0,0},{1,4},{4,6},{1,2},{4,7},{3,5.5},{2,5},{5,8},{1.5,4}};//各个城市点的开始时间和结束时间TW[CITY_NUM][0]是各个最早时间TW[CITY_NUM][1]是最迟到时间

	 }
	 for (j=1;j<CITY_NUM;j++)  //对各个城市点的最晚时间进行排序
		 for (i=0;i<CITY_NUM-j;i++)
			 if (ordertime[i].endtime>ordertime[i+1].endtime)
			 {
				 temp=ordertime[i];
                 ordertime[i]=ordertime[i+1];
                 ordertime[i+1]=temp;
			 }
	printf("按时间窗最晚时间从小到大排序各个点的编号为:");//the sorted  end time case);
	outfile<<"\n\n按时间窗最晚时间从小到大排序各个点的编号为:"<<endl;
    for (i=0;i<CITY_NUM;i++)  //输出按最晚时间从早到晚排序后的各个城市点的序号
    {
	   if (i%25==0) printf("\n"); 
	   printf("%8d",ordertime[i].num);  
	  // printf("->时间窗后边沿%1.1f\n",ordertime[i].endtime); 
    }
    printf("\n");



	for (i=0;i<CITY_NUM;i++) 
	{
		outfile<<setw(7)<<ordertime[i].num;
	}
	outfile<<endl;



    for (i=0;i<CITY_NUM;i++) //输出各个排序后各个城市点对应的最晚时间
    {
	   if (i%9==0) printf("\n"); 
	   printf("[%1.1f,%1.1f]",ordertime[i].starttime,ordertime[i].endtime);
	  //printf("%1.1f ",ordertime[i].endtime);   
    }

	 for (i=0;i<CITY_NUM;i++)
	 {
		 outfile<<setw(3.5)<<"["<<ordertime[i].starttime<<","<<ordertime[i].endtime<<"]";
	 }
      
}
 
/*************************************    
		计算两任务之间的最大距离
*************************************/
double max_dist()
{
int i,j;
    double max_dist=0.0;
	for (i=0;i<CITY_NUM;i++)
	    for (j=0;j<CITY_NUM;j++)
	        if (D[i][j]>max_dist)
		       max_dist=D[i][j];
	
    return max_dist;
}
/*************************************
    求子路径长度
*************************************/
 double calc_sublen(int *route)
{
	 int n,i,j;
     double len=0.0;
	 for(n=0;n<MAX_ROUTE_LEN-1;n++)
	 {
	     i=route[n];
		 j=route[n+1];
         len+=D[i][j];
		 if (j==0) break;//route[]中存放的是计算出的子路径的编号eg:route[n]={0 3 1 5 0 8 4 0 6 7 0 2 0 0 0}当出现第二个0时为一条子路径
	 }
	 return(len);
}

/*************************************
    求各子路径长度之和
*************************************/
 double calc_length(int *route)
{
	 int n,i,j;
     double len=0.0;
	 //for(int k=0;k<ANT_NUM;k++)
	 //{
		// printf("第%d只蚂蚁寻找的路径为:\n",k);
		// outfile<<"第"<<k<<"只蚂蚁寻找的路径各段距离为:"<<endl;
		 for(n=0;n<MAX_ROUTE_LEN-1;n++)
		 {
			 i=route[n]; //route[]中存放的是计算出的子路径的编号eg:route[n]={0 3 1 5 0 8 4 0 6 7 2 0 0 0}
		      j=route[n+1];
		      len+=D[i][j];//
		     if (i==j) break;  //当i和j均为0时则该子路径结束
		    printf("%d->%d length:%1.1f    ",i,j,D[i][j]);
		   outfile<<i<<"->"<<j<<"  length:"<<D[i][j];
		    outfile<<setw(3);
		 }
	
	 printf("该车所走路径长度为:%1.1f\n\n",len);
	 outfile<<"\n该车所走路径长度为:"<<len<<endl<<endl;
	 //}
	 return(len);
}
/***************************************
   求所用车辆数
***************************************/
int calc_vehicle(int *route)
{ 
	int vehicle=0;
	int n,i,j;
	for(n=0;n<MAX_ROUTE_LEN-1;n++)
	{
        i=route[n];
	    j=route[n+1];
		if ((i==0)&&(j!=0)) vehicle++;
	}
	return (vehicle);
}

/***************************************
   判断路径是否满足时间窗约束
***************************************/
int time_case(int *route)
{
	int n,tflag,i,j;
	double atime;
	atime=0;tflag=1;
	outfile<<"\n找到的最好路径中到达的各个时间值分别为:\n";
	for (n=0;n<MAX_ROUTE_LEN-1;n++)
	{
		i=route[n];
		j=route[n+1];
		atime=atime+T[i]+D[i][j]/50;
         atime1=atime;
        printf("从第%d点-第%d点,到达j点并完成任务时的时间为atime(计算方法atime=atime+T[i]+D[i][j]/50)%4.1f\n",i,j,atime);
		outfile<<i<<"->"<<j<<"   overtime:"<<atime<<endl;
		if (j==0)
			atime=0;
		else
			if (atime<(TW[j][0])||(atime>TW[j][1]))//到达时间不在时间窗内
			{ 
				hflag=1;
			    tflag=0;   //0,表示不满足
		        printf("不符合时间窗的点=%d->%d(但通过计算惩罚值可以接受的点)\n",i,j);
				outfile<<"不符合时间窗的点"<<i<<"->"<<j<<"  但该点是通过计算惩罚值可以接受的点"<<endl;
			}
		if (i==j) break;
	}
	return(tflag);
}


/***************************************
     蚂蚁随机分布在各任务上
****************************************/
void init_random()
{
	int k,rand1;
    for(k=0;k<ANT_NUM;k++) 
	{   
		ant[k].tour[0]=0;
	    rand1=rand()%(CITY_NUM-1)+1;
		ant[k].tour[1]=rand1;
	}
}
/*****************************************
             蚂蚁均匀分布在城市上
******************************************/
void init_uniform()
{
	int k,may[CITY_NUM],num,i,j;
	num=0;
	for (i=1;i<CITY_NUM;i++)  //挑选出满足时间窗的节点编号并纪录满足时间窗的节点数目
		if ((D[0][i]/50>=TW[i][0])&&(D[0][i]/50<=TW[i][1]))//车辆到达时间正好在i点的时间窗中
		{ //如果从配货中心到各个点的时间(距离除以速度D[0][i]/50)大于该点所允许的最早时间(TW[i][0])或者小于该点的最晚时间(TW[i][1])
		 	may[num]=i;//符合上述要求的点的编号纪录到一个数组may[CITY_NUM]中
			num=num+1;//纪录符合条件的点的个数
		}
	j=0;
	for(k=0;k<ANT_NUM;k++) //把所有的蚂蚁都放在中心,然后把满足时间窗的蚂蚁放入下一个节点
	{
		ant[k].tour[0]=0;//所有蚂蚁一开始都在中心(tour[0]是纪录子路径编号的数组,其中的0是子路径第几个节点),0代表陪送中心编号0
		j=k%num;
		ant[k].tour[1]=may[j];//把符合时间条件的点的标号放入第k只蚂蚁的第一个要走的节点中
	}
}


/*****************************************
          初始化禁忌表
******************************************/
void init_tabu()
{
	int j;
	tabu[0]=1;  //1表示禁止走到那个任务点,0表示允许
	for (j=1;j<CITY_NUM;j++)
		tabu[j]=0;
}

/**************************************
          初始化tau(边上的信息素)
***************************************/
void init_tau_by_value(double value)
{
    int i,j;
	for (i=0;i<CITY_NUM;i++)
        for (j=0;j<CITY_NUM;j++)
	        tau[i][j]=value;
}

/***************************************
            清除全局更新轨迹量
****************************************/
void clear_global_update()
{  
   int i,j;
   for (i=0;i<CITY_NUM;i++)
	   for (j=0;j<CITY_NUM;j++)
	       detatau[i][j]=0.0;//detatau[i][j]是指蚂蚁k在本次循环中留在边(i,j)上的信息素
}

/***************************************
             进行全局更新(所有蚂蚁都找到一条子路径后进行的更新,第k只蚂蚁找到的路径各个边上的信息素均为(Q/ant[k].len))
****************************************/
void add_global_update()
{  
   int k,j;
   for (k=0;k<ANT_NUM;k++)
	   for (j=0;j<MAX_ROUTE_LEN-1;j++)
	       if ((ant[k].tour[j]!=0)||(ant[k].tour[j+1]!=0))//当第k只蚂蚁走过的点或下一个点不是中心时
		   {
			   if(hflag==0)
			   {
			   detatau[ant[k].tour[j]][ant[k].tour[j+1]]+=(Q/ant[k].len);  //第k只蚂蚁在本次子路径中边(j->j+1)上的信息素
               detatau[ant[k].tour[j+1]][ant[k].tour[j]]+=(Q/ant[k].len); //第k只蚂蚁在本次子路径回路上边(j+1->j)上的信息素
			   }
			   else  //	if (atime<(TW[j][0])||(atime>TW[j][1]))/
			   {
				    detatau[ant[k].tour[j]][ant[k].tour[j+1]]+=(Q/ant[k].len);
					if(atime1<(TW[j][0]))//如果实际到达时间atime1比时间窗的最早时间早则信息素=信息素*(1-实际到达时间与时间窗边沿的差/时间窗)
					detatau[ant[k].tour[j]][ant[k].tour[j+1]]=detatau[ant[k].tour[j]][ant[k].tour[j+1]]*(  1-( TW[j][0]-atime1 )/( TW[j][1]-TW[j][0] ) );
				    //早于时间窗前沿
					else  
							detatau[ant[k].tour[j]][ant[k].tour[j+1]]=detatau[ant[k].tour[j]][ant[k].tour[j+1]]*(  1-(atime1 -TW[j][1] )/( TW[j][1]-TW[j][0] ) );
                            //晚于时间窗后沿

			   }
		   }
		   else
              detatau[ant[k].tour[j]][ant[k].tour[j+1]]=0; //否则第k只蚂蚁在本次子路径中边(j->j+1)上的信息素为0
}

/***************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -