遗传算法实现 解车辆路径问题(vrp)

问题就是每辆车有一定的容量限制,接的人有一定的重量,然后安排多辆车去接使车的行驶路程最短

只实现了容量限制,没有实现车辆的路程限制

客人位置按极坐标排序

初始解生成比较重要,比较简单的就是派一辆车从第一个客人开始接,直到快要装满重量,但是不一定超过重量就不接,按如下规则:

可以理解为当所有车总容量之和 和 所有客人重量 差不多时,那么即使超重也加上,这样说不定在后面的杂交中产生好的解

然后就是基本的杂交变异操作

基因的编码方式如下,总共有客人数量的长度,然后每个位置表示当前客人坐哪辆车


#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#include
using namespace std;

const int CUS_MAXN = 100;
const double pi = acos(-1);
const int VEH_MAX = 10;
const int INF=1<<30;

int generation=100000;	//代数 
double mutate_p_swap=600;   //1---1000 
double mutate_p_rev=20; //1---1000
double mutate_p_shift=800;
const int PRO=10000; 	//变异概率的分母 
//const string NAME="A-n33-k6.vrp";

class Customer {
public:
	int x, y;
	int demand;
	double polar;
	double distance;
	Customer();
	Customer(int, int, int);

	bool operator<(const Customer&) const;

	// double operator-(const Customer&);
};

class Vehicle
{
public:
	vector cus_vec;
	double x;
	double y;
	double polar;
	double distance;
	double length;
	int cap;
	int cap_remain;

	void clear();
	bool push(int c); // 输入的是顾客的index

	int get_num(); // 返回顾客的数列
	void get_coor(); // 得到这辆货车的新的坐标

	bool operator<(const Vehicle& b) const;
	void optimate();
	Vehicle();
	~Vehicle();
};

class Individual
{
public:
	int chromosome[CUS_MAXN]; // 染色体序列
	Vehicle veh[VEH_MAX];
	
	double fitness;		//适应度
	double unfitness;

	void update();
	bool is_satisfy();
	double get_ufit();
	double get_fit();
	
	Individual& operator = (const Individual &b); 
	Individual();
	~Individual();
};



int cus_num; // 顾客数
int veh_num; // 货车数
int opt_dis; // 最优解
int best_ind; // 当前最优解
int CAP; // 每辆货车的容量

double tightness; // 宽松度
double Rc, Rd; // ~~~

Individual best;//当前得到的最优解 
const int popul_size = 30; //每一代人口数量
double dis[CUS_MAXN][CUS_MAXN]; //距离矩阵

Customer cus[CUS_MAXN];
Individual popul[popul_size];
	
	
	
//初始解 
void ini_popul();
//binary tournament 
int selection(int tournament_size);
//交叉变异 
Individual gene_two_point_crossover(int curr1,int curr2,Individual &ans1, Individual &ans2); 
//进化换代 
void evolution(); 

//突变 
void gene_swap(Individual &ans);
void gene_shift(Individual &ans);
void gene_reverse(Individual &ans);

double get_polar(double, double); // 角度

double get_dis_of_cus(const Customer&, const Customer&);
double get_dis(double, double);

void get_d();

bool ini_data();


//输入坐标返回极坐标
double get_polar(double x, double y) {
	double polar;
	if (x > 0 && y >= 0) {
		return polar = atan(1.0 * y / x);
	}
	if (x == 0) {
		if (y > 0) return polar = pi / 2;
		else return polar = 3 * pi / 2;
	}
	if (x < 0 && y >= 0) {
		return polar = pi - atan(-1.0 * y / x);
	}
	if (x < 0 && y < 0) {
		return polar = pi + atan(1.0 * y / x);
	}
	if (x > 0 && y < 0) {
		return polar = 3 * pi / 2 + atan(-1.0 * x / y);
	}
}

double get_dis(double x, double y) {
	return sqrt(x * x + y * y);
}

double get_dis_of_cus(const Customer& a, const Customer& b) {
	return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

void get_d() {
	for (int i = 0; i <=cus_num; i++) {
		for (int j = 0; j <= cus_num; j++) {
			if (i==j){
				dis[i][j]=0;
			}
			else if (i==0){
				dis[i][j]=get_dis(cus[j-1].x,cus[j-1].y);
			}
			else if (j==0){
				dis[i][j]=get_dis(cus[i-1].x,cus[i-1].y);
			}
			dis[i][j] = get_dis_of_cus(cus[i-1], cus[j-1]);
		}
	}
}

bool ini_data() {
	ifstream in("A-n33-k6.vrp");
	//ifstream in(NAME);
	if (!in.is_open()) return false;
	string s;
	if (getline(in, s)) {
		//cout<> veh_num >> opt_dis;
		//cout<> cus_num;
		//cout<> CAP;
		for (int i=0;i> t;
		is >> x >> y;
		for (int i = 0; i < cus_num-1; i++) {
			getline(in, s);
			is.str(s); is.clear();
			is >> t;
			is >> cus[i].x >> cus[i].y;
			cus[i].x -= x;
			cus[i].y -= y;
			cus[i].polar = get_polar(cus[i].x, cus[i].y);
			//cout<> t;
		is >> t;
		for (int i = 0; i < cus_num-1; i++) {
			getline(in, s);
			is.str(s); is.clear();
			is >> t;
			is >> cus[i].demand;
			sum_all += cus[i].demand;
			//cout<= 0.97) {
			Rc = 0.6;
		}
		else if (tightness >= 0.94){
			Rc=0.75;
		}
		else Rc = 0.9;
	}
	in.close();
	cus_num-=1;
	sort(cus , cus + cus_num);
	get_d();
	cout << "data initial successful!" << endl;
	cout<<"cus "<=veh_num){
				//cout<<"veh_num"< ave_demand && k < veh_num) {
			demands = cus[i].demand;
			++k;
		}
		// 每个种子为最大的距离
		if (cus[i].distance > seed[k]) {
			seed[k] = cus[i].distance;
			index[k] = i;
		}
	}

	int seed_index[2][CUS_MAXN] = {0}; // 每一个顾客的两个最优种子的编号
	int belong_index[2][CUS_MAXN]; // 种子对应车辆的编号
	for (int i = 0; i < cus_num; i++) {
		double dif0 = 1000000, dif1 = 1000000;
		for (int j = 0; j < veh_num; j++) {
			double dif = get_dis_of_cus(cus[i], cus[index[j]]);
			if (dif < dif0) { // 距离小于第一个种子
				dif1 = dif0;
				seed_index[1][i] = seed_index[0][i];
				seed_index[0][i] = index[j];
				belong_index[1][i] = belong_index[0][i];
				belong_index[0][i] = j;
				dif0 = dif;
			} else if (dif < dif1) { // 距离小于第二个种子
				seed_index[1][i] = index[j];
				belong_index[1][i] = j;
				dif1 = dif;
			}
		}
	}
	for (int i = 0; i < cus_num; i++) {
		if (seed_index[1][i] == 0) {
			seed_index[1][i] = seed_index[0][i];
			belong_index[1][i] = belong_index[0][i];
		}
	}
	// 获得两个种子的概率
	int pro[2][CUS_MAXN];
	for (int i = 0; i < cus_num; i++) {
		for (int j = 0; j < 2; j++) {
			pro[j][i] = dis[0][i + 1] + dis[i + 1][seed_index[j][i] + 1]
			            - dis[0][seed_index[j][i] + 1];
		}
		for (int j = 0; j < 2; j++) {
			pro[j][i] = (int)(100.0 * pro[j][i] / (pro[0][i] + pro[1][i]));
		}
	}
	srand((unsigned)time(0));
	// 根据概率获取15个初始解
	// int init_num = 15;
	for (int i = 0 ; i < popul_size; i++) {
	//for (int i = popul_size/2 ; i < popul_size; i++) {
		bool isV[VEH_MAX] = {0};
		int cnt = 0;
		for (int j = 0; j < cus_num; j++) {
			int random = rand() % 100;
			if (random > pro[0][j]) {
				// popul[i].veh[belong_index[0][j]].push(j - 1);
				popul[i].chromosome[j] = belong_index[0][j];
			} else {
				// popul[i].veh[belong_index[1][j]].push(j - 1);
				popul[i].chromosome[j] = belong_index[1][j];
			}
			if (!isV[popul[i].chromosome[j]]) {
				++cnt;
				isV[popul[i].chromosome[j]] = true;
			}
		}
		if (cnt == veh_num)
			popul[i].update();
		// ++init_num;
	}
	
	*/
}


int selection(int tournament_size){
	int selected = rand() % popul_size;
	for (int i = 1; i < tournament_size; i++){
		int r = rand() % popul_size;
		if (popul[r].fitness > popul[selected].fitness){
			selected = r;
		}
	}
	return selected;
}


void evolution(){
	for(int T=0;T= tmp.fitness && popul[j].unfitness >= tmp.unfitness){
				popul[j]=tmp;found=1;break;
			}
		}
		if(!found) for(int j=0;j= tmp.fitness && popul[j].unfitness <= tmp.unfitness){
				popul[j]=tmp;found=1;break;
			}
		}
		if(!found) for(int j=0;j= tmp.unfitness){
				popul[j]=tmp;found=1;break;
			}
		} 
		if(!found) for(int j=0;j pt2) swap(pt1, pt2);
		//cout<=ans2.fitness&&ans1.unfitness>=ans2.unfitness){
			return ans1;
		}
		else return ans2;
		/*
		 
		for (int i=0;ians2.fitness){
					return ans1;
				}
				else return ans2;			
			}
			else return ans1;
		}
		if (ans2.is_satisfy()) {
			ans2.update();
			return ans2;	
		}*/
		//Sleep(10000);
	//}
	//return ans1;
}


void gene_swap(Individual &ans){
	//int len = cus_num;
	int pt1 = rand() % cus_num;
	int pt2 = rand() % cus_num;
	//if (pt1 > pt2) swap(pt1, pt2);
	//cout< pt2) swap(pt1, pt2);
	if (pt1%2==0&&pt1+1=0){
		swap(ans.chromosome[pt1], ans.chromosome[pt1-1]);	
	}
//	ans.fitness = ans.compute_fitness(ans);//gai
}



void gene_reverse(Individual &ans){
	int len = cus_num;
	int pt1 = rand() % len; //pt1: [0, cus_num-1]
	int pt2 = rand() % len; //pt2: [0, cus_num-1]
	if (pt1 > pt2) swap(pt1, pt2);
	
	for (int i = pt1, j = pt2; i <= j; i++, j--){
		swap(ans.chromosome[i], ans.chromosome[j]);
	}
	//ans.fitness = ans.compute_fitness(ans);// gai
}


/

Customer::Customer() {
	x = y = demand = 0;
}

Customer::Customer(int x, int y, int d) {
	this->x = x;
	this->y = y;
	this->demand = d;
	polar = get_polar(x, y);
	distance = get_dis(x, y);
}
 
bool Customer::operator<(const Customer & c) const {
	if (polar == c.polar) return distance < c.distance;
	return polar < c.polar;
}




Vehicle::Vehicle() {
	cap = CAP;
	cap_remain = CAP;
}


Vehicle::~Vehicle() {
}

void Vehicle::clear() {
	cus_vec.clear();
	cap_remain = CAP;
}

bool Vehicle::push(int c) {
	if (cap_remain >= cus[c].demand) {
		cus_vec.push_back(c);
	//	cout< Rc) {
			cus_vec.push_back(c);
			cap_remain -= cus[c].demand;
			return 1;
		}
		return 0;
	}
}

int Vehicle::get_num() {
	return cus_vec.size();
}

void Vehicle::get_coor() {
	double sumx = 0, sumy = 0;
	int l = get_num();
	for (int i = 0; i < l; i++) {
		sumx += cus[cus_vec[i]].x;
		sumy += cus[cus_vec[i]].y;
	}
	x = sumx / l;
	y = sumy / l;
	polar = get_polar(x, y);
	distance = get_dis(x, y);
}

bool Vehicle::operator<(const Vehicle& v)const {
	if (polar != v.polar) {
		return polar < v.polar;
	}
	else return distance < v.distance;
}

void Vehicle::optimate() {
	bool isv[cus_num];
	int l=cus_vec.size();
	memset(isv,0,sizeof(isv));
	vector v;
	double len=0;
	int now=0;
	double len_min=INF;
	int t;
	int min_p=0;
//	cout<<"veh"<=veh_num) cout<<"no"<0)
		{
			if (!veh[chromosome[i]].push(i)) return 0;	
		}
		else return 0;
	}
	for (int i=0;i0)
				if (!veh[chromosome[i]].push(i)) return 0;
			else return 0;
			//veh[i].get_coor();
		}*/
		for (int i=0;i0)
			//每次生成儿子不用判断是否合理 
			//veh[chromosome[i]].push(i);
			veh[chromosome[i]].cus_vec.push_back(i);
			veh[chromosome[i]].cap_remain-=cus[i].demand;
			//veh[i].get_coor();
		}
		for (int i=0;ibest.fitness&&unfitness==0){
			best=*this;
		}
		sort(veh,veh+veh_num);
		for (int i=0;i




你可能感兴趣的:(Acm算法相关,课程大作业)