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

来源:互联网 发布:淘宝售馨图片 编辑:程序博客网 时间:2024/05/21 21:02

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

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

客人位置按极坐标排序

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

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

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

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


#include <fstream>#include <sstream>#include <algorithm>#include <vector>#include <iostream>#include <cmath>#include<cstring>#include <ctime>#include <cstdlib>#include<windows.h>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---1000double 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<int> cus_vec;double x;double y;double polar;double distance;double length;int cap;int cap_remain;void clear();bool push(int c); // 输入的是顾客的indexint 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<<s<<endl;getline(in, s);istringstream is(s);is >> veh_num >> opt_dis;//cout<<veh_num<<endl;getline(in, s);is.str(s); is.clear();//cout<<is.str()<<endl;is >> cus_num;//cout<<cus_num<<endl;getline(in, s);is.str(s); is.clear();is >> CAP;for (int i=0;i<popul_size;i++){for (int j=0;j<veh_num;j++){popul[i].veh[j].clear();}}getline(in, s);int t;//获取相对坐标int x,y;getline(in, s);is.str(s); is.clear();is >> 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<<cus[i].x<<cus[i].y<<endl;cus[i].distance = get_dis(cus[i].x, cus[i].y);}getline(in, s);double sum_all = 0;getline(in, s);is.str(s); is.clear();is >> 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<<cus[i].demand<<endl;}tightness = 1.0 * sum_all / (veh_num * CAP);if (tightness >= 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 "<<cus_num<<endl;//Sleep(5000);return 1;}void ini_popul(){//srand((unsigned)time(NULL)); int num;int p=0;//cout<<popul_size<<endl;//for(int i=0;i<popul_size;){for(int i=0;i<popul_size/2;){num=rand()%cus_num;//cout<<num<<endl;p=0;bool f=false;for (int j=0;j<veh_num;j++){popul[i].veh[j].clear();}for (int j=0;j<cus_num;){int k=(num+j)%cus_num;//cout<<k<<veh_num<<endl;//cout<<"v[i].cap"<<popul[i].veh[p].cap_remain<<endl;if (p>=veh_num){//cout<<"veh_num"<<p;//p=0;f=false;break;}if (popul[i].veh[p].push(k)) {//cout<<"remain: "<<popul[i].veh[p].cap_remain<<endl; popul[i].chromosome[k]=p;if (p==veh_num-1){f=true;}j++;}else p++;}//cout<<p<<endl;if (f){popul[i].update();//cout<<"kkkkkkkkkk"<<endl;i++;//cout<<i<<endl;}//cout<<"kk"<<endl;}/*double ave_demand = 0;for (int i = 0; i < cus_num; i++)ave_demand += cus[i].demand;ave_demand /= veh_num;int seed[VEH_MAX] = {0};int index[VEH_MAX];int demands = 0;int k = 0;// 分类,index[] 是种子对应的顾客编号。for (int i = 0; i < cus_num; i++) {demands += cus[i].demand;if (demands > 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<generation;T++){int father1=selection(2);int father2=selection(2);Individual son[2];Individual tmp;//cout<<father1<<" "<<father2<<endl; tmp=gene_two_point_crossover(father1,father2,son[0],son[1]);//cout<<"xxx"<<endl;bool found=0;for(int j=0;j<popul_size;j++){if(popul[j].fitness >= tmp.fitness && popul[j].unfitness >= tmp.unfitness){popul[j]=tmp;found=1;break;}}if(!found) for(int j=0;j<popul_size;j++){ if(popul[j].fitness >= tmp.fitness && popul[j].unfitness <= tmp.unfitness){popul[j]=tmp;found=1;break;}}if(!found) for(int j=0;j<popul_size;j++){if(popul[j].fitness <= tmp.fitness && popul[j].unfitness >= tmp.unfitness){popul[j]=tmp;found=1;break;}} if(!found) for(int j=0;j<popul_size;j++){if(popul[j].fitness <= tmp.fitness && popul[j].unfitness <= tmp.unfitness){popul[j]=tmp;found=1;break;}}}}Individual gene_two_point_crossover(int curr1,int curr2,Individual &ans1, Individual &ans2){//int T=3; //while(T--){ans1=popul[curr1];ans2=popul[curr2];//while(1){//cout<<curr1<<" cur"<<curr2<<endl;//curr1=selection(2);//curr2=selection(2);/*for (int i=0;i<cus_num;i++){cout<<ans1.chromosome[i]<<' ';}cout<<endl;for (int i=0;i<cus_num;i++){cout<<ans2.chromosome[i]<<' ';}cout<<endl;*///交叉 int pt1 = rand() % cus_num;int pt2 = rand() % cus_num;if (pt1 > pt2) swap(pt1, pt2);//cout<<pt1<<" "<<pt2<<endl;for(int i=pt1;i<=pt2;i++)swap(ans1.chromosome[i], ans2.chromosome[i]);/*for (int i=0;i<cus_num;i++){cout<<ans1.chromosome[i]<<' ';}cout<<endl;for (int i=0;i<cus_num;i++){cout<<ans2.chromosome[i]<<' ';}cout<<endl;cout<<endl;Sleep(5000);*///变异 //cout<<pt1<<" x "<<pt2<<endl;int p_mutate = (rand()%PRO);//变异概率范围:0-0.01if (p_mutate < mutate_p_swap){gene_swap(ans1);gene_swap(ans2);}double p_mutate2 = (rand()%PRO);//cout<<"rand"<<p_mutate2<<endl;if (p_mutate2 < mutate_p_shift){gene_shift(ans1);gene_shift(ans2);}ans1.update();ans2.update();if (ans1.fitness>=ans2.fitness&&ans1.unfitness>=ans2.unfitness){return ans1;}else return ans2;/* for (int i=0;i<cus_num;i++){cout<<ans1.chromosome[i]<<' ';}cout<<endl;for (int i=0;i<cus_num;i++){cout<<ans2.chromosome[i]<<' ';}cout<<endl;cout<<endl;*//*if (ans1.is_satisfy()) {ans1.update();if (ans2.is_satisfy()) {ans2.update();if (ans1.fitness>ans2.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<<pt1<<" swap "<<pt2<<endl;swap(ans.chromosome[pt1], ans.chromosome[pt2]);//ans.fitness = ans.compute_fitness(ans);//gai}void gene_shift(Individual &ans){//int len = cus_num;int pt1 = rand() % cus_num;//int pt2 = rand() % cus_num;//if (pt1 > pt2) swap(pt1, pt2);if (pt1%2==0&&pt1+1<cus_num){swap(ans.chromosome[pt1], ans.chromosome[pt1+1]);}if (pt1%2==1&&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<<c<<" c num and demand "<<cus[c].demand<<endl;;cap_remain -= cus[c].demand;//cout<<"cap "<<cap_remain<<endl;//cout<<"custom "<<c<<endl;//cout<<"push true"<<endl;return 1;}else {// 根据Rc判断是否接受解if (cap_remain * 1.0 / cus[c].demand > 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<int> v;double len=0;int now=0;double len_min=INF;int t;int min_p=0;//cout<<"veh"<<endl;for (int k=0;k<l;k++){len_min=INF;for (int i=0;i<l;i++){t=cus_vec[i];if (!isv[t]&&dis[now][t+1]<len_min){min_p=t;len_min=dis[now][t+1];}}//cout<<len_min<<endl;len+=len_min;isv[min_p]=1;now=min_p+1;v.push_back(min_p);}//cout<<"end"<<endl;len+=dis[min_p+1][0];cus_vec=v;length=len;return ;/*for (int i = 0; i < cus_vec.size() - 1; i++){double i_x = cus[cus_vec[i]].x;double i_y = cus[cus_vec[i]].y;double i1_x = cus[cus_vec[i + 1]].y;double i1_y = cus[cus_vec[i + 1]].y;if (get_dis(i1_x, i1_y) < get_dis(i_x, i_y) / 2){swap(cus_vec[i], cus_vec[i + 1]);}}*/}Individual::Individual() {fitness=0;unfitness=INF;//cout<<"ini_indi"<<endl;for (int i=0;i<veh_num;i++){veh[i].clear();}}Individual::~Individual() {}Individual& Individual::operator = (const Individual &b){//memcpy(chromosome,b.chromosome,cus_num);for (int j=0;j<cus_num;j++){chromosome[j]=b.chromosome[j];}for (int i=0;i<veh_num;i++){veh[i]=b.veh[i];}fitness=b.fitness;unfitness=b.unfitness;}bool Individual::is_satisfy(){for (int i=0;i<veh_num;i++){veh[i].clear();}bool isv[veh_num];memset(isv,0,veh_num);for (int i=0;i<cus_num;i++){//if (chromosome[i]<0||chromosome[i]>=veh_num) cout<<"no"<<endl;//cout<<i<<" remain "<<veh[chromosome[i]].cap_remain<<endl;isv[chromosome[i]]=1;if (veh[chromosome[i]].cap_remain>0){if (!veh[chromosome[i]].push(i)) return 0;}else return 0;}for (int i=0;i<veh_num;i++){if (!isv[i]) return 0;}return 1;}void Individual::update() {for (int i=0;i<veh_num;i++){veh[i].clear();}/*for (int i=0;i<cus_num;i++){if (veh[chromosome[i]].cap_remain>0)if (!veh[chromosome[i]].push(i)) return 0;else return 0;//veh[i].get_coor();}*/for (int i=0;i<cus_num;i++){//if (veh[chromosome[i]].cap_remain>0)//每次生成儿子不用判断是否合理 //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;i<veh_num;i++){veh[i].get_coor();}get_ufit();get_fit();if (fitness>best.fitness&&unfitness==0){best=*this;}sort(veh,veh+veh_num);for (int i=0;i<veh_num;i++){for (int j=0;j<veh[i].cus_vec.size();j++){chromosome[veh[i].cus_vec[j]]=i;}}return ; }double Individual::get_ufit() {double sum = 0;for (int i = 0; i < veh_num; i++) {//计算总超过的容量if (veh[i].cap_remain < 0) {sum -= veh[i].cap_remain;}}return unfitness = sum / CAP;}double Individual::get_fit() {double len = 0;for (int i = 0; i < veh_num; i++) {//double sum = 0;//int l = veh[i].cus_vec.size();veh[i].optimate();len+=veh[i].length;}return fitness = 1 / len;}/////////////////////////////////////////////////////// int main(){if(!ini_data()){cout<<"have no file"<<endl;return 0;}srand((unsigned)time(0)); cout<<"veh_num :"<<veh_num<<endl;cout<<"cus_num :"<<cus_num<<endl;cout<<"CAP:"<<CAP<<endl;cout<<"optimal :"<<opt_dis<<endl;cout<<"tightness :"<<tightness<<endl;ini_popul();/*Individual tmp;tmp=popul[0];for (int j=0;j<cus_num;j++){cout<<tmp.chromosome[j]<<" ";}cout<<endl;*//*for (int i=0;i<popul_size;i++){for (int j=0;j<cus_num;j++){cout<<popul[i].chromosome[j]<<" ";}cout<<endl;}*/for (int i=0;i<veh_num;i++){for (int j=0;j<best.veh[i].cus_vec.size();j++){cout<<best.veh[i].cus_vec[j]<<" ";}cout<<endl;}if (best.fitness==0) cout<<"000"<<endl;else cout<<1/(best.fitness)<<endl;cout<<endl;cout<<endl;//cout<<Rc<<" "<<endl;evolution();//bool isv[33]={0};for (int i=0;i<veh_num;i++){for (int j=0;j<best.veh[i].cus_vec.size();j++){cout<<" "<<best.veh[i].cus_vec[j]<<" ";//isv[best.veh[i].cus_vec[j]]=1;}cout<<endl;//cout<<"veh_num "<<i<<endl;}/*for (int i=0;i<cus_num;i++) {if (isv[i]==0) cout<<"false"<<endl; }*/if (best.fitness==0) cout<<"000"<<endl;else cout<<1/(best.fitness)<<endl;} 



0 0