问题就是每辆车有一定的容量限制,接的人有一定的重量,然后安排多辆车去接使车的行驶路程最短
只实现了容量限制,没有实现车辆的路程限制
客人位置按极坐标排序
初始解生成比较重要,比较简单的就是派一辆车从第一个客人开始接,直到快要装满重量,但是不一定超过重量就不接,按如下规则:
可以理解为当所有车总容量之和 和 所有客人重量 差不多时,那么即使超重也加上,这样说不定在后面的杂交中产生好的解
然后就是基本的杂交变异操作
基因的编码方式如下,总共有客人数量的长度,然后每个位置表示当前客人坐哪辆车
#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---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<int> 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<<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.01
if (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;
}