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