遗传算法 Genetic Algorithms
遗传算法 Genetic Algorithms
遗传算法是一种“adaptive heuristic search algorithm”(自适应启发式搜索算法),虽不明、但觉厉。其实遗传算法的思路很朴素,实现起来也并不复杂(用到一点点生物学科普级别的知识,学科交叉还挺有趣的)。
遗传算法模拟的是自然界中,一个种群内生物基因的传递模式。可以预料到在大自然“优胜劣汰”的筛选机制下,那些能适应环境的强者往往更容易与配偶结合将自己的基因保留到下一代;而体弱多病的弱者会面临死亡,基因无法保存的下场。对于一个种群而言,这种淘汰机制可以让更多的优质基因得以留存,有利于种群的延续。
思路
现在我们假设:
- 问题的一个解,对应于一个“个体”(这是一种只有一个染色体的简单物种)
- 一个解应该由一个字符串来表示,其中一个字符对应于“基因”
- 存在一个判断机制来充当“优胜劣汰”机制,帮助我们判断哪些解更有价值
- 并让这些解“交配”,期望在下一代解中优质解变得更多
上图中有大、中、小三个红框:最小的代表一个解是由一个字符串,或者数字字符排列组合而成的;中间的指一个完整的解;而最大的红框则是指全体解集合(这里有优质解也有劣质解,需要我们甄别)
适应度函数
每一个解都有有一个,用来定量判断这个基因“竞争能力”的值,适应度函数。“竞争能力”更强的个体有更高的概率活到下一代,或者与配偶繁衍子代;但是由于种群内个体的数量是固定的,那些“竞争能力”弱的个体会死掉,被其它“竞争能力”更强的个体取代。
这样、下一代群体中个体的适应度函数的平均值会高于上一代(也就是这些解是问题更佳的解)。当父代与子代群体中的个体之间没有明显差异了,代表进化收敛了,这个算法也就找到了最优质的解。
变异
自然界中,决定后代基因的不仅仅是爹娘双方染色体的融合,还包括变异。引入变异可以提高种群个体的多样性,有利于提高种群的平均适应度函数,进而找到最优解。
算法流程
在原始种群被生成后(通常是随机出来的),遗传算法会采取以下措施来产生下一代:
- 选择环节
对于适应度函数高的个体,给予更大的优先级来让它们保存与繁衍
- 交配环节
对于从“选择环节”中调出的两个个体,让它们随机地结合,产生后代(就像两个染色体整合形成新的染色休那样!)。
- 变异环节
以相对较小的概率任意改变子代的若干基因,提高种群差异性,防止种群进化的进程过早地收敛。
用遗传算法完成一次光荣的进化!
用遗传算法打印,“welcome to ticmis's blog”
C++
// C++ program to create target string, starting from
// random string using Genetic Algorithm
#include <bits/stdc++.h>
using namespace std;
// Number of individuals in each generation
#define POPULATION_SIZE 100
// Valid Genes
const string GENES = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP"\
"QRSTUVWXYZ 1234567890,'.-;:_!\"#%&/()=?@${[]}";
// Target string to be generated
const string TARGET = "Welcome to ticmis's blog";
// Function to generate random numbers in given range
int random_num(int start, int end)
{
int range = (end-start)+1;
int random_int = start+(rand()%range);
return random_int;
}
// Create random genes for mutation
char mutated_genes()
{
int len = GENES.size();
int r = random_num(0, len-1);
return GENES[r];
}
// create chromosome or string of genes
string create_gnome()
{
int len = TARGET.size();
string gnome = "";
for(int i = 0;i<len;i++)
gnome += mutated_genes();
return gnome;
}
// Class representing individual in population
class Individual
{
public:
string chromosome;
int fitness;
Individual(string chromosome);
Individual mate(Individual parent2);
int cal_fitness();
};
Individual::Individual(string chromosome)
{
this->chromosome = chromosome;
fitness = cal_fitness();
};
// Perform mating and produce new offspring
Individual Individual::mate(Individual par2)
{
// chromosome for offspring
string child_chromosome = "";
int len = chromosome.size();
for(int i = 0;i<len;i++)
{
// random probability
float p = random_num(0, 100)/100;
// if prob is less than 0.45, insert gene
// from parent 1
if(p < 0.45)
child_chromosome += chromosome[i];
// if prob is between 0.45 and 0.90, insert
// gene from parent 2
else if(p < 0.90)
child_chromosome += par2.chromosome[i];
// otherwise insert random gene(mutate),
// for maintaining diversity
else
child_chromosome += mutated_genes();
}
// create new Individual(offspring) using
// generated chromosome for offspring
return Individual(child_chromosome);
};
// Calculate fitness score, it is the number of
// characters in string which differ from target
// string.
int Individual::cal_fitness()
{
int len = TARGET.size();
int fitness = 0;
for(int i = 0;i<len;i++)
{
if(chromosome[i] != TARGET[i])
fitness++;
}
return fitness;
};
// Overloading < operator
bool operator<(const Individual &ind1, const Individual &ind2)
{
return ind1.fitness < ind2.fitness;
}
// Driver code
int main()
{
srand((unsigned)(time(0)));
// current generation
int generation = 0;
vector<Individual> population;
bool found = false;
// create initial population
for(int i = 0;i<POPULATION_SIZE;i++)
{
string gnome = create_gnome();
population.push_back(Individual(gnome));
}
while(! found)
{
// sort the population in increasing order of fitness score
sort(population.begin(), population.end());
// if the individual having lowest fitness score ie.
// 0 then we know that we have reached to the target
// and break the loop
if(population[0].fitness <= 0)
{
found = true;
break;
}
// Otherwise generate new offsprings for new generation
vector<Individual> new_generation;
// Perform Elitism, that mean 10% of fittest population
// goes to the next generation
int s = (10*POPULATION_SIZE)/100;
for(int i = 0;i<s;i++)
new_generation.push_back(population[i]);
// From 50% of fittest population, Individuals
// will mate to produce offspring
s = (90*POPULATION_SIZE)/100;
for(int i = 0;i<s;i++)
{
int len = population.size();
int r = random_num(0, 50);
Individual parent1 = population[r];
r = random_num(0, 50);
Individual parent2 = population[r];
Individual offspring = parent1.mate(parent2);
new_generation.push_back(offspring);
}
population = new_generation;
cout<< "Generation: " << generation << "\t";
cout<< "String: "<< population[0].chromosome <<"\t";
cout<< "Fitness: "<< population[0].fitness << "\n";
generation++;
}
cout<< "Generation: " << generation << "\t";
cout<< "String: "<< population[0].chromosome <<"\t";
cout<< "Fitness: "<< population[0].fitness << "\n";
}
Python3
# Python3 program to create target string, starting from
# random string using Genetic Algorithm
import random
# Number of individuals in each generation
POPULATION_SIZE = 100
# Valid genes
GENES = '''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP
QRSTUVWXYZ 1234567890,'.-;:_!"#%&/()=?@${[]}'''
# Target string to be generated
TARGET = "Welcome to ticmis's blog"
class Individual(object):
'''
Class representing individual in population
'''
def __init__(self, chromosome):
self.chromosome = chromosome
self.fitness = self.cal_fitness()
@classmethod
def mutated_genes(self):
'''
create random genes for mutation
'''
global GENES
gene = random.choice(GENES)
return gene
@classmethod
def create_gnome(self):
'''
create chromosome or string of genes
'''
global TARGET
gnome_len = len(TARGET)
return [self.mutated_genes() for _ in range(gnome_len)]
def mate(self, par2):
'''
Perform mating and produce new offspring
'''
# chromosome for offspring
child_chromosome = []
for gp1, gp2 in zip(self.chromosome, par2.chromosome):
# random probability
prob = random.random()
# if prob is less than 0.45, insert gene
# from parent 1
if prob < 0.45:
child_chromosome.append(gp1)
# if prob is between 0.45 and 0.90, insert
# gene from parent 2
elif prob < 0.90:
child_chromosome.append(gp2)
# otherwise insert random gene(mutate),
# for maintaining diversity
else:
child_chromosome.append(self.mutated_genes())
# create new Individual(offspring) using
# generated chromosome for offspring
return Individual(child_chromosome)
def cal_fitness(self):
'''
Calculate fitness score, it is the number of
characters in string which differ from target
string.
'''
global TARGET
fitness = 0
for gs, gt in zip(self.chromosome, TARGET):
if gs != gt: fitness+= 1
return fitness
# Driver code
def main():
global POPULATION_SIZE
#current generation
generation = 1
found = False
population = []
# create initial population
for _ in range(POPULATION_SIZE):
gnome = Individual.create_gnome()
population.append(Individual(gnome))
while not found:
# sort the population in increasing order of fitness score
population = sorted(population, key = lambda x:x.fitness)
# if the individual having lowest fitness score ie.
# 0 then we know that we have reached to the target
# and break the loop
if population[0].fitness <= 0:
found = True
break
# Otherwise generate new offsprings for new generation
new_generation = []
# Perform Elitism, that mean 10% of fittest population
# goes to the next generation
s = int((10*POPULATION_SIZE)/100)
new_generation.extend(population[:s])
# From 50% of fittest population, Individuals
# will mate to produce offspring
s = int((90*POPULATION_SIZE)/100)
for _ in range(s):
parent1 = random.choice(population[:50])
parent2 = random.choice(population[:50])
child = parent1.mate(parent2)
new_generation.append(child)
population = new_generation
print("Generation: {}\tString: {}\tFitness: {}".\
format(generation,
"".join(population[0].chromosome),
population[0].fitness))
generation += 1
print("Generation: {}\tString: {}\tFitness: {}".\
format(generation,
"".join(population[0].chromosome),
population[0].fitness))
if __name__ == '__main__':
main()
Output:
Generation: 0 String: BLQx{m?"d}#tz#zXQ"#xw1Pv Fitness: 22
Generation: 1 String: WokJyv' a.oH{4Ch6u.EyK$_ Fitness: 22
Generation: 2 String: r&s4Sd7f![MAm?_R9#5 f3wg Fitness: 22
Generation: 3 String: r&s4Sd7f![MAm?_R9#5 f3wg Fitness: 22
Generation: 4 String: r&s4Sd7f![MAm?_R9#5 f3Zg Fitness: 22
Generation: 5 String: BLQx{m?"d}#tz#zXQ"#xw1Pv Fitness: 22
Generation: 6 String: r&s4Sd7f![MAm?_R9#5 f3wg Fitness: 22
Generation: 7 String: [&s4Sd7f![MAm?_R9#5 f3Zg Fitness: 22
.
.
.
Generation: 858 String: Welcome to t'cmis's blog Fitness: 1
Generation: 859 String: Welcome to tTcmis's blog Fitness: 1
Generation: 860 String: Welcome to tCcmis's blog Fitness: 1
Generation: 861 String: Welcome to tCcmis's blog Fitness: 1
Generation: 862 String: Welcome to ticmis's blog Fitness: 0
遗传算法 Genetic Algorithms的更多相关文章
- 基于遗传算法(Genetic Algorithm)的TSP问题求解(C)
基于遗传算法的TSP问题求解(C) TSP问题: TSP(Travelling salesman problem): 译作“旅行商问题”, 一个商人由于业务的需要,要到n个城市,每个城市之间都有一条路 ...
- 遗传算法Genetic Algorithm
遗传算法Genetic Algorithm 好家伙,回回都是这个点,再这样下去人估计没了,换个bgm<夜泊秦淮>,要是经典咏流传能投票选诗词,投票选歌,俺一定选这个 开始瞎叨叨 遗传算法的 ...
- 遗传算法 Genetic Algorithm
2017-12-17 19:12:10 一.Evolutionary Algorithm 进化算法,也被成为是演化算法(evolutionary algorithms,简称EAs),它不是一个具体的算 ...
- 超详细的遗传算法(Genetic Algorithm)解析
https://blog.csdn.net/u010451580/article/details/51178225 https://www.jianshu.com/p/c82f09adee8f 00 ...
- 【智能算法】超详细的遗传算法(Genetic Algorithm)解析和TSP求解代码详解
喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 文章声明 此文章部分资料和代码整合自网上,来源太多已经无法查明出处,如侵犯您的权利,请联系我删除. 00 目录 遗传算法定义 生 ...
- MIP启发式算法:遗传算法 (Genetic algorithm)
*本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 本文主要讲述启发式算法中的遗传算法.遗传算法也是以local search为核心框架,但在表现形式上和hill climbing, ta ...
- 遗传算法(Genetic Algorithm)——基于Java实现
一.遗传算法原理介绍 遗传算法(Genetic Algorithm)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法.遗传算法是从代表问 ...
- 遗传算法中几种不同选择算子及Python实现
前言 本文对遗传算法中的几种选择策略进行了总结, 其中包括: Proportionate Roulette Wheel Selection Linear Ranking Selection Expon ...
- 【遗传编程/基因规划】Genetic Programming
目录 背景介绍 程序表示 初始化 (Initialization) Depth定义 Grow方法 Full方法 Ramped half-and-half方法 适应度(Fitness)与选择(Selec ...
随机推荐
- 微信小程序制作日常生活首页
1.手机上效果预览 不知道为啥上传后是如此的高糊画质(手机画质很好) 微信小程序日常生活首页手机效果演示 2.开发者工具效果图 3.真机调试 4.项目的目录结构 5.核心代码 5.1 app.json ...
- golang中经常会犯的一些错误
0.1.索引 https://waterflow.link/articles/1664080524986 1.未知的枚举值 我们现在定义一个类型是unit32的Status,他可以作为枚举类型,我们定 ...
- 15行python代码实现人脸识别
方法一:face_recognition import cv2 import face_recognition img_path = "C:/Users/CJK/Desktop/1.jpg& ...
- Windows下自动云备份思源笔记到Gitee
前言 思源笔记是一款本地笔记为主的软件,其目前提供了148元/year的付费同步功能,但对于21世纪中国难民而言还是太贵啦. 条件允许的同学还是使用官方的同步,支持下作者. 所以,就在思考有没有白嫖的 ...
- Java 编码那些事(二)
建议先阅读:Java 编码那些事(一) 现在说说编码在Java中的实际运用.在使用tomcat的时候,绝大部分同学都会遇到乱码的问题,查查文档,google一下解决方案啥的,都是设置这里,设置那里,或 ...
- CSS基础知识筑基
01.CSS 简介 CSS 指层叠样式表 (Cascading Style Sheets),对HTML网页内容进行统一外观样式设计和管理,给网页进行各种装饰,让她变得美观,是HTML的化妆师.(Cas ...
- 前端html和css总结
1.html知识总结 1.1 表格的的相关属性 属性 表示 border-collapse 设置表格的边框是否被合并为一个单一的边框 cellpadding 单元格边距 cellspacing 单元格 ...
- JS学习笔记 (五) 函数进阶
1.函数基础 1.1 函数的基本概念 函数是一段JavaScript代码,只被定义一次,但是可以被调用或者执行许多次.函数是一种对象,可以设置属性,或调用方法. 函数中的参数分为实参和形参.其中,形参 ...
- JAVA语言学习-面向对象(1)
类与对象 类 类是JAVA语言中重要的复合型数据类型().类的实现包括两个部分:成员变量和成员方法("方法"可以看作是C语言中的函数) 类的声明 要使用类,首先得对其声明.声明一个 ...
- Redisson源码解读-公平锁
前言 我在上一篇文章聊了Redisson的可重入锁,这次继续来聊聊Redisson的公平锁.下面是官方原话: 它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程.所有请 ...