# 2017华为软挑——遗传算法

## 2. 编码

///////////////////////////////////////*遗传算法 start*////////////////////////////////////////////////////
# define POPSIZE 10		//种群内个体数量
# define MAXGENS 100		//最大的迭代次数
static int NVARS = 3;		//变量个数，即用以表示基因型的bit数
# define PXOVER 0.85		//交换率
# define PMUTATION 0.3	//突变率

struct genotype
{
double gene[MAX_NODE];
double fitness;
double upper[MAX_NODE];
double lower[MAX_NODE];
double rfitness;
double cfitness;
};

struct genotype population[POPSIZE + 1];
struct genotype newpopulation[POPSIZE + 1];
///////////////////////////////////////*遗传算法 end*//////////////////////////////////////////////////////

///////////////////////////////////////*遗传算法 start*////////////////////////////////////////////////////
//遗传算法搜索
void my_GAsearch()
{
int seed = 772002;
srand((unsigned)time(NULL));
GA_initialize(seed);
evaluate();
keep_the_best();

for (int generation = 0; generation < MAXGENS; generation++)
{
selector(seed);
crossover(seed);
mutate(seed);
evaluate();
elitist();
}
}

//选择两个个体进行交叉变异
void crossover(int &seed)
{
const double a = 0.0;
const double b = 1.0;
int mem;
int one;
int first = 0;
double x;

for (mem = 0; mem < POPSIZE; ++mem )
{
//x = r8_uniform_ab ( a, b, seed );
x = Dou_uniform_ab( a, b);

if ( x < PXOVER )
{
++first;

if ( first % 2 == 0 )
{
Xover ( one, mem, seed );
}
else
{
one = mem;
}
}
}
return;
}

//选出本轮中最优和最差的个体，将本轮中最好的个体赋值给最后一个个体，将上轮中最坏的个体赋值给当前最坏的个体
void elitist()
{
int i;
double best;
int best_mem;
double worst;
int worst_mem;

best = population[0].fitness;
worst = population[0].fitness;

for (i = 0; i < POPSIZE - 1; ++i )
{
if ( population[i+1].fitness < population[i].fitness )
{

if ( best <= population[i].fitness )
{
best = population[i].fitness;
best_mem = i;
}

if ( population[i+1].fitness <= worst )
{
worst = population[i+1].fitness;
worst_mem = i + 1;
}

}
else
{

if ( population[i].fitness <= worst )
{
worst = population[i].fitness;
worst_mem = i;
}

if ( best <= population[i+1].fitness )
{
best = population[i+1].fitness;
best_mem = i + 1;
}
}
}
//
//  If the best individual from the new population is better than
//  the best individual from the previous population, then
//  copy the best from the new population; else replace the
//  worst individual from the current population with the
//  best one from the previous generation
//
if ( population[POPSIZE].fitness <= best )
{
for ( i = 0; i < NVARS; i++ )
{
population[POPSIZE].gene[i] = population[best_mem].gene[i];
}
population[POPSIZE].fitness = population[best_mem].fitness;
}
else
{
for ( i = 0; i < NVARS; i++ )
{
population[worst_mem].gene[i] = population[POPSIZE].gene[i];
}
population[worst_mem].fitness = population[POPSIZE].fitness;
}

return;
}

//对遗传算法的效果进行评价
void evaluate()
{
int member;
int i;
double x[800+1];
int temp_flow(0);	//流量标记
std::vector<int> m_server;	//取到的时候对应的server
for ( member = 0; member < POPSIZE; member++ )
{
int flow(0), cost(0);
double sum=0;
for ( i = 0; i < NVARS; i++ )
{
x[i+1] = population[member].gene[i];
}

std::vector<int> temp = GA_get_server_pos(x);
population[member].fitness = get_fitness(temp, cost, flow);
if (flow >= needed_flow)
{
if (min_cost > cost)
{
min_cost = cost;
m_server = temp;
}
}	//满足了流量要求，则要求其最小费用
else
{
if (temp_flow < flow)
{
temp_flow = flow;
m_server = temp;
}
}	//不满足流量需求，则满足最大流量需求
}
xjbs_search(m_server);	//局部搜索最优
GA_update(m_server);
return;
}

//使用搜索出来的局部最优解去更新遗传的参数
void GA_update(std::vector<int> m_server)
{
for (int i = 0; i < NVARS; i++)
{
for (int j = 0; j < POPSIZE; j++)
{
if (CheckIsServer(i, m_server))
{
population[j].gene[i] += Dou_uniform_ab(0.0, 0.2);;
}
//else
//	population[j].gene[i] = 0.2;
}
}
}

//计算自定义的度量函数
double get_fitness(std::vector<int>& server, int& cost, int& flow)
{
if(server.size()<=0)
{
cout << "get 0 server pos in GA, ERROR" << endl;
return (-MAXINT);
}
Dij_init(server);
flow = 0;
cost = Dij_MinCostFlow(net_node_num, (net_node_num+1), flow);
cost = cost+server.size()*server_cost;
cout << "server_num:" << server.size() <<" ,loop: min cost: " << cost <<
" , max flow: " << flow << " / " << needed_flow << endl;

//return flow;
if(flow >= needed_flow)
{
if(min_cost > cost)
{
//cout << "find better: " << cost << endl;
min_server = server;
min_cost = cost;
min_path = path;
}
return cost;
}
else
{
return (needed_flow-flow)*10*cost;
}
}

//根据遗传算法得到的参数的解，得到服务器的位置
std::vector<int> GA_get_server_pos(double* data)
{
std::vector<int> result;
if(nullptr == data)
return result;

for(int i=0; i<NVARS-1; i++)
{
if(data[i] > 0.88)
result.push_back(i);
}

return result;
}

//my new design function of the distribution
int Int_uniform_ab(int a, int b)
{   int tmp;
tmp = (rand() % (b-a+1))+ a;
return tmp;
}

//遗传算法初始化
void GA_initialize(int& seed)
{
//  Initialize variables within the bounds
std::vector<int> server;// = min_server;
for (int i=0; i<client_node_num; i++)
{
server.push_back(client_node[i].innode[0]);
}

NVARS = net_node_num;//+1;	//设置GA算法的参数变量的个数为网络中节点的个数

for (int i = 0; i < NVARS; i++)
{
for (int j = 0; j < POPSIZE; j++)
{
population[j].fitness = 0;
population[j].rfitness = 0;
population[j].cfitness = 0;
population[j].lower[i] = 0;	//代表不选中该点作为服务器
population[j].upper[i] = 1;  //代表选中该点作为服务器
if (CheckIsServer(i, must_server))
{
population[j].gene[i] = 1.0;
}
else if (CheckIsServer(i, forbid_server))
{
population[j].gene[i] = 0.0;
}
else population[j].gene[i] = r8_uniform_ab(0.2, 0.9, seed);
//population[j].gene[i] = Dou_uniform_ab(0.0, 1.0);
}
}
}

//保存最好的个体到最后一个中去
void keep_the_best( )
{
int cur_best;
int mem;
int i;

cur_best = 0;

for ( mem = 0; mem < POPSIZE; mem++ )
{
if ( population[POPSIZE].fitness < population[mem].fitness )
{
cur_best = mem;
population[POPSIZE].fitness = population[mem].fitness;
}
}
//
//  Once the best member in the population is found, copy the genes.
//
for ( i = 0; i < NVARS; i++ )
{
population[POPSIZE].gene[i] = population[cur_best].gene[i];
}

return;
}

//变异
void mutate(int &seed )
{
const double a = 0.0;
const double b = 1.0;
int i;
int j;
double lbound;
double ubound;
double x;

for ( i = 0; i < POPSIZE; i++ )
{
for ( j = 0; j < NVARS; j++ )
{
x = r8_uniform_ab ( a, b, seed );
//x = Dou_uniform_ab( a, b);
if ( x < PMUTATION )
{
lbound = population[i].lower[j];
ubound = population[i].upper[j];
population[i].gene[j] = r8_uniform_ab ( lbound, ubound, seed );
//population[i].gene[j] = Dou_uniform_ab( lbound, ubound );
}
}
}

return;
}

//通过随机种子选取a,b之间的随机数
double r8_uniform_ab( double a, double b, int &seed )
{
int i4_huge = 2147483647;
int k;
double value;

if ( seed == 0 )
{
std::cerr << "\n";
std::cerr << "R8_UNIFORM_AB - Fatal error!\n";
std::cerr << "  Input value of SEED = 0.\n";
exit ( 1 );
}

k = seed / 127773;

seed = 16807 * ( seed - k * 127773 ) - k * 2836;

if ( seed < 0 )
{
seed = seed + i4_huge;
}

value = ( double ) ( seed ) * 4.656612875E-10;

value = a + ( b - a ) * value;

return value;
}

//随机选择a,b之间的随机数
double Dou_uniform_ab(double a, double b)
{
double tmp;
//rand() / double(RAND_MAX)可以生成0~1之间的浮点数
tmp = a + static_cast<double>(rand())/RAND_MAX*(b-a);
return tmp;
}

//计算相对适应度和累积适应度，然后根据适应度进行选择和赋值
void selector(int &seed)
{
const double a = 0.0;
const double b = 1.0;
int i;
int j;
int mem;
double p;
double sum;
double max_value(0);

//  Find the total fitness of the population.
sum = 0.0;
for (mem = 0; mem < POPSIZE; mem++)
{
max_value = max_value<population[mem].fitness?population[mem].fitness:max_value;
}
//for ( mem = 0; mem < POPSIZE; mem++ )
//{
//    sum += max_value - population[mem].fitness;
//}

//  Calculate the relative fitness of each member.
for ( mem = 0; mem < POPSIZE; mem++ )
{
population[mem].rfitness = (max_value-population[mem].fitness) / max_value;
}

//  Calculate the cumulative fitness.
population[0].cfitness = population[0].rfitness;
for ( mem = 1; mem < POPSIZE; mem++ )
{
population[mem].cfitness = population[mem-1].cfitness +
population[mem].rfitness;
}

//  Select survivors using cumulative fitness.
for ( i = 0; i < POPSIZE; i++ )
{
p = r8_uniform_ab ( a, b, seed );
//p = Dou_uniform_ab(a,b);
if ( p < population[0].cfitness )
{
newpopulation[i] = population[0];
}
else
{
for ( j = 0; j < POPSIZE; j++ )
{
if ( population[j].cfitness <= p && p < population[j+1].cfitness )
{
newpopulation[i] = population[j+1];
}
}
}
}

//  Overwrite the old population with the new one.
for ( i = 0; i < POPSIZE; i++ )
{
population[i] = newpopulation[i];
}

return;
}

//基因的交叉操作
void Xover( int one, int two, int &seed )
{
int i;
int point;
double t;
//  Select the crossover point.
//point = i4_uniform_ab ( 0, NVARS - 1, seed );
point = Int_uniform_ab(0, NVARS-1);

//  Swap genes in positions 0 through POINT-1.
for ( i = 0; i < point; i++ )
{
t                       = population[one].gene[i];
population[one].gene[i] = population[two].gene[i];
population[two].gene[i] = t;
}

return;
}
///////////////////////////////////////*遗传算法 end*//////////////////////////////////////////////////////

## 3. 总结

### 混合遗传算法是很常见的策略。比如遗传算法应用于排序问题，生成新一代种群之后，将个体中相邻两个元素交换次序，如果新的个体适应度更高则保留。这种贪心的变种往往能大幅度提高遗传算法的收敛速率。3.2 个人观点

兔子朝着比现在高的地方跳去。他们找到了不远处的最高山峰。但是这座山不一定是珠穆朗玛峰。这就是局部搜索，它不能保证局部最优值就是全局最优值。
兔子喝醉了。他随机地跳了很长时间。这期间，它可能走向高处，也可能踏入平地。但是，他渐渐清醒了并朝最高方向跳去。这就是模拟退火。
兔子们吃了失忆药片，并被发射到太空，然后随机落到了地球上的某些地方。他们不知道自己的使命是什么。但是，如果你过几年就杀死一部分海拔低的兔子，多产的兔子们自己就会找到珠穆朗玛峰。这就是遗传算法。
兔子们知道一个兔的力量是渺小的。他们互相转告着，哪里的山已经找过，并且找过的每一座山他们都留下一只兔子做记号。他们制定了下一步去哪里寻找的策略。这就是禁忌搜索。

m_buddy

• 擅长领域：
• 机器瞎学