2017华为软挑——遗传算法
1. 概述
变异:
群体:个体的集合;在比赛中种群的大小也意味着计算量的大小,因而在大图的时候可以适当减小种群的数量。
适应度:个体的适应性、生命力的度量;在比赛中使用最小费用最大流计算得到的代价来作为它的代价函数,也可以采用拉格朗日松弛来简化数学模型。
选择(复制):适应度高的个体,被大自然选择并生存的机率高;采用随机类似赌轮的方式进行。
交叉:个体间的基因交叉,生物遗传的主要行为;
变异:个体继承父代基因时的基因变异,生物进化的主要行为。
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; //取到的时候对应的serverfor ( 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 boundsstd::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.1 遗传算法深化
遗传算法的全局搜索能力强,但局部搜索能力就不行了。解释:比如对于一条染色体,遗传算法并不会去看看这条染色体周围局部的染色体适应度怎么样,是否比这条染色体好。遗传算法会通过变异和交叉产生新的染色体,但新产生的染色体可能和旧染色差的很远。因此遗传算法的局部搜索能力差。
对于一些局部搜索算法如:梯度法、爬山法和贪心法等算法的局部搜索能力强,运算效率也高。若能够将问题相关的启发知识引入这些算法,这些算法的威力不可小觑。受此启发,人们提出了混合遗传算法,将遗传算法和这些算法结合起来。混合遗传算法的框架是遗传算法的,只是生成新一代种群之后,对每个个体使用局部搜索算法寻找个体周围的局部最优点。
混合遗传算法是很常见的策略。比如遗传算法应用于排序问题,生成新一代种群之后,将个体中相邻两个元素交换次序,如果新的个体适应度更高则保留。这种贪心的变种往往能大幅度提高遗传算法的收敛速率。
3.2 个人观点
兔子朝着比现在高的地方跳去。他们找到了不远处的最高山峰。但是这座山不一定是珠穆朗玛峰。这就是局部搜索,它不能保证局部最优值就是全局最优值。
兔子喝醉了。他随机地跳了很长时间。这期间,它可能走向高处,也可能踏入平地。但是,他渐渐清醒了并朝最高方向跳去。这就是模拟退火。
兔子们吃了失忆药片,并被发射到太空,然后随机落到了地球上的某些地方。他们不知道自己的使命是什么。但是,如果你过几年就杀死一部分海拔低的兔子,多产的兔子们自己就会找到珠穆朗玛峰。这就是遗传算法。
兔子们知道一个兔的力量是渺小的。他们互相转告着,哪里的山已经找过,并且找过的每一座山他们都留下一只兔子做记号。他们制定了下一步去哪里寻找的策略。这就是禁忌搜索。
2017华为软挑——遗传算法相关推荐
- O准备如何苟进复赛圈?华为软挑开挂指南(附赛题预测)
这篇文章纯粹是心血来潮,原因是去年上传到github的参赛代码,前几天又有两个人star和fork了. 记得star热潮还是去年4月复赛刚结束的那几天,厚着脸皮在八大赛区的群里发消息求关注,之后就陷入 ...
- 2022华为软挑比赛(初赛笔记)
文章目录 2022华为软挑(初赛笔记) 1. 赛题要求 2. 解决方案 2.1 挑选适合的边缘节点 2.2 第一轮:最大分配 2.3 第二轮:均值分配 总结 本文仓库地址: Github-CodeCr ...
- 2020华为软挑热身赛代码开源-思路大起底(华为软件精英挑战赛编程闯关)
本文首发于个人公众号[两猿社],后台回复[华为],获取完整开源代码链接. 昵称:lou_shang_shi_bian_tai 成绩:0.032 社长没有针对硬件做任何优化,热身赛成绩也一般.但有些比赛 ...
- 2021华为软挑部分答疑——哪些你有错却总是找不到的地方,我来带你找啦(含标准输入代码)
前期工作: 2021华为软挑初探--代码实现 2021华为软挑再探--代码实现 1 关于打包 在windows系统下,先把你写的程序写在src里面的CodeCraft-2021里面 然后在这个页面,将 ...
- 华为软挑赛2023-复赛笔记
前言 比赛介绍 参考初赛博客: 华为软挑赛2023-初赛笔记_没有梦想的大白兔的博客-CSDN博客 赛题变动 官网赛题: 华为云论坛_云计算论坛_开发者论坛_技术论坛-华为云 (huaweicloud ...
- 2020华为软挑热身赛-这些坑我帮你踩过了(华为软件精英挑战赛编程闯关)
本文始发于个人公众号[两猿社]. 声明,为保证比赛公平,本文不会提供比赛源码,仅提供思路与踩坑经验. 他来了,他来了,他带着面试绿卡走来了. 他来了,他来了,他带着20w大奖走来了. 一年一度的华为软 ...
- 2019华为软挑代码总结-交通规则模拟
文章目录 前言 三.数据读入后怎么跑呢? 总结 四.怎么看效果? 前言 以前一份代码的阅读,2019华为软挑 三.数据读入后怎么跑呢? 思路: 1.创建地图类,将地图中每个路口到其他路口最短路径保存. ...
- 华为软挑赛2023-初赛笔记
前言 比赛介绍 官方链接: 2023华为软件精英挑战赛--普朗克计划 (huaweicloud.com) 赛题介绍 场景介绍 官方赛题介绍: 2023华为软件精英挑战赛初赛赛题及相关材料发布_2023 ...
- 2018华为软挑--模拟退火+FF解决装箱问题【C++代码】
算法简介: 装箱问题是一个NP完全问题,求解全局最优解有很多种方法:遗传算法.禁忌搜索算法.蚁群算法.模拟退火算法等等,本次使用模拟退火,它的优点是在参数合适的情况下基本上可以100%得到全局最优解, ...
- 2022华为软挑编程问题报错总结
for i in number_feature: TypeError: 'int' object is not iterable的错误 错误原因:是因为在python里,整型(int)数据是不能直接用 ...
最新文章
- ISP【三】———— raw读取、不同格式图片差异
- mysqlls_mysql基本命令
- 关于GitHub推送时发生Permission denied (publickey)的问题
- 想拥有最新的微软嵌入式技术 就赶快加入微软嵌入式专家社区吧!
- android 自定义图片上传,android自定义ImageView仿图片上传(示例代码)
- C++中transform的用法
- case when then else 详解
- @transactional注解失效情况
- Java并发编程之线程定时器ScheduledThreadPoolExecutor解析
- JVM 内存监控 (1.8)
- 国家邮政局:前10月邮政行业业务收入同比增长17.8%
- 喜欢 TypeScript 的人,一点都不比 Python 少
- 20 世纪 10 大算法
- 深度学习总概论(超神之路)
- power iso linux启动盘,怎么用poweriso制作u盘启动盘win10_poweriso制作u盘启动盘win10详细步骤...
- Socket 简介及面试题
- quot 云计算 quot 是计算机,云计算是什么意思?
- Vscode连接远程服务器出现‘Acquiring lock on/home/~’问题
- 苹果官方首曝iOS 15!这些经典iPhone都要被弃
- 虚拟主机mysql数据库大小,香港虚拟主机的网站数据库空间不够怎么办