基于论文《最大团问题改进的遗传算法》
论文地址:
代码:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//#define DEBUG
const int max_size = 1600;//数据容量上限
const int N = 10;//搜索数据
const int M = N / 2;
const double alpha = 0.001;
const int delta = 3;
const double lamda = 0.1;
const int cirle = 10000;
const double beta = 0.9;
int bound;
int t = 0;//演化代数
int edges[max_size][max_size];//邻接矩阵
const int size = 1534;//实际数据大小,需要自己设定
int U[max_size];
int Us[N][max_size];
double P[N];
int better[M];
void initial_P();
void update_P();
void local_search(int U[]);
void create_U();
bool judge_allsame();
void select_better(int length);
void change();
void lets_run();
//在迭代之前初始化P
void initial_P()
{
for(int i = 0;i<N;i++)
{
int sum = 0;
for(int j = 0;j<N;j++)
sum += Us[j][i];
P[i] = (double)sum / N;
}
}
void update_P()
{
for(int i = 0;i<N;i++)
{
int sum = 0;
for(int j = 0;j<M;j++)
sum += Us[better[j]][i];
P[i] = P[i] * (1 - lamda) + lamda * (double)sum / M;
}
}
void local_search(int U[])
{
//步骤一
int W [max_size];
int S [max_size];//记录的是W中标号为1的下标值
//将数据进行压缩
int len = 0;//实际数据长度
for(int i = 0;i<size;i++){
W[i] = U[i];
if(U[i] == 1)
len++;
}
while(len > 0)
{
int dex;
int chose;
//随机从W中选取一个顶点chose
int num = 0;
for(int i = 0;i<size;i++)
if(W[i])
S[num++] = i;
chose = S[rand()%num];
len--;
//以alpha的概率将dex从S中去除
double alpha_rand = (rand()%100001)/100000.0;
if(alpha_rand < alpha)
U[chose] = 0;
else{
for(int i = 0;i<size;i++)
{
if(i != chose && U[i] == 1 && edges[chose][i] == 0){
U[i] = 0;
W[i] = 0;
}
}
}
}
//步骤二
len = 0;
for(int i = 0;i<size;i++)
{
W[i] = (U[i] )? 0:1;
if(!U[i])
len++;
}
while(len > 0)
{
int dex;
int chose;
int num = 0;
for(int i = 0;i<size;i++)
if(W[i])
S[num++] = i;
chose = S[rand()%num];
W[chose] = 0;
len--;
int plag = 0;
for(int i = 0;i<size;i++)
{
if(i != chose && U[i] == 1 && edges[chose][i] == 0){
plag = 1;
break;
}
}
if(!plag)
U[chose] = 1;
}
}
void create_U()
{
if(t == 0){
for(int i = 0;i<size;i++)
U[i] = rand()%2;
}
else
{
//初始化US
for(int i = 0;i<N;i++)
{
for(int j = 0;j<size;j++)
Us[i][j] = 0;
}
for(int i = 0;i<N;i++)
{
int type = (rand()%delta+1) + bound;
while(1)
{
int dex = rand() % size;
if(Us[i][dex] == 0){
Us[i][dex] = 1;
type--;
if(type == 0)
break;
}
}
}
}
}
bool judge_allsame()
{
for(int i = 0;i<size;i++)
{
int num = Us[0][i];
for(int j = 1;j<N;j++)
if(num != Us[j][i])
return 0;
}
return 1;
}
void select_better(int length)
{
int fx[N];
for(int i = 0;i<N;i++)
{
int sum = 0;
for(int j = 0;j<size;j++)
if(Us[i][j] == 1)
sum++;
fx[i] = sum;
}
for(int i = 0;i<length;i++)
{
int max = i;
int j;
for(j = i+1;j<N;j++)
if(fx[max] < fx[j])
max = j;
if(max != j)
{
int m = fx[max];
fx[max] = fx[j];
fx[j] = m;
better[i] = max;
}
}
}
void change()
{
int U_part[M][max_size];
for(int i = 0;i<M;i++)
{
for(int j = 0;j<size;j++)
{
//判断是否进行变异
double pri = (rand()%100001)/100000.0;
if(pri < beta)
{
pri = (rand()%100001)/100000.0;
if(pri < P[j])
U_part[i][j] = 1;
else
U_part[i][j] = 0;
}
else
U_part[i][j] = Us[better[0]][j];
}
}
//进行求极大团
for(int i = 0;i<M;i++)
{
local_search(U_part[i]);
}
//将种群进行归并
int dex = 0;
for(int i = 0;i<M;i++)
{
if(dex != better[i]){
for(int j = 0;j<size;j++)
Us[dex][j] = Us[better[i]][j];
}
dex++;
}
for(int i = M;i<N;i++)
{
for(int j = 0;j<size;j++)
Us[i][j] = U_part[i-M][j];
}
}
void lets_run()
{
bound = 0;
int plag = 0;
while(true)
{
//初始化
if(t == 0){
create_U();
local_search(U);
for(int i = 0;i<size;i++){
if(U[i] == 1)
bound++;
}
t++;
}
//随机产生N个编码
if(plag == 1 || plag == 0){
create_U();
//对N个编码进行校正,生成N个极大团
for(int i = 0;i<N;i++)
local_search(Us[i]);
}
//初始化变异率向量
initial_P();
//选择N/2个较优的个体构成父体
if(plag == 2)
select_better(M);
//对选择出的N/2个父体,更新P
update_P();
//对t代的父体中最优的个体进行M次变异操作,再进行局部搜索并和之前
//的父体进行合并
change();
t++;
//选择最优的个体,并进行输出
select_better(1);
int bound1 = 0;
for(int i = 0;i<size;i++)
if(Us[better[0]][i] == 1)
bound1++;
if (t > cirle)
{
printf("Result:t:%d bound:%d\n",t,(bound > bound1)?bound:bound1);
break;
}
if(bound1 > bound)
{
plag = 1;
bound = bound1;
printf("t:%d bound:%d\n", t,bound);
continue;
}
printf("t:%d bound:%d\n", t,bound);
if(judge_allsame)
plag = 1;
else
plag = 2;
}
}
int main()
{
srand((unsigned)time(NULL));
FILE *in = fopen("E:/stest/test_26.txt","r");
char char1,char2,*c;
int size1,len_num,dex_i,dex_j;
fscanf(in,"%d%d",&size1,&len_num);
#ifdef DEBUG
printf("len_edge:%d;len_num:%d\n",size1,len_num);
#endif
for(int i = 0;i<size;i++){
for(int j = 0;j<size;j++)
{
edges[i][j] = 0;
}
}
for(int i = 0;i<len_num;i++){
fscanf(in,"%s%d%d",&c, &dex_i, &dex_j);
#ifdef DEBUG
printf("%c %d %d\n",c,dex_i,dex_j);
#endif
edges[dex_i-1][dex_j-1] = 1;
edges[dex_j-1][dex_i-1] = 1;
}
lets_run();
}