我用Anylogic写了一个遗传算法

我最近一直在学习遗传算法,学习一个东西最好的办法就是用上它,然后我就用python写了一个简单的解多元二次方程的遗传算法,当我写完以后就开始了另一个想法: 可以用Anylogic写一个遗传算法吗?
然后我就开始了:

先确定求解的问题

建立一个简单的方程:y=x_1x_1+x_2x_2+x_3x_3+x_4x_4+x_5x_5
目标设为求 min y
也就是求 min (x_1
x_1+x_2x_2+x_3x_3+x_4x_4+x_5x_5)
参数x_1,x_2,x_3,x_4和x_5的范围都设为[-5,5]
上面这个问题很简单,一眼就可以看出来解是(0,0,0,0,0)
但是这里只是为了试验Anylogic是否可以写一个简单的遗传算法,就没有必要一开始就解复杂的问题。

进行遗传编码

上面的问题很简单,我们就直接按照x_1,x_2,x_3,x_4和x_5进行编码,遗传基因为五位,用实数进行编码,[x_1,x_2,x_3,x_4,x_5]。

产生初始群体的方法

这里就采用最简单的方法:随机(也不会其它方法)
初始种群采用随机函数生成每个基因。

获得交叉父代的方法与遗传算子

通常采用的选择的方法有轮盘赌选择、(mu+lambda)选择、竞争选择等
选择遗传父代采用轮盘赌选择,就是按照每个个体的适应度确定选择的概率;生存选择采用(mu+lambda)方法。
轮盘赌:
从群体中随机选择,每个个体的选择概率根据个体的适应度来决定。
(mu+lambda):
lambda个子代由mu个父代产生,进行生存选择时丢弃所有的父代,在子代选择出最优的mu个个体构成新的群体。

遗传算子采用算数算子
子代采用权重继承父代的基因
算数算子: x’=x1lambda1+x2lambda2 (lambda1+lambda2=1,lambda1>0,lambda2>0)

这些都确定好了,可以开始写代码(建模)

应该是建模!
首先是建立一个工程,命名就直接一点,就叫GA,然后就进入工程main智能体。
然后呢?
遗传算法的主要过程是怎么样的呢?
首先要确定用什么来储存基因编码,在python可以直接用列表来储存,Anylogic也有类似的类(Linkedlist),对就是用LinkedList来储存基因。
那每个个体除了基因还有适应度,怎同时储存基因和适应度呢?
也可以直接用LinkedList,但是在建模过程中会显得很不清晰,所以可以直接采用建立智能体。
在Agent库里拖拽agent到main里,选择Agent type only ,智能体类型命名为Individual在这里插入图片描述
在工程树中双击该类型,进入Individual类型编辑,在智能体中添加一个LinkedList和变量就可以表示一个个体的基因和适应度。
在这里插入图片描述
然后将LinkedList和变量改为gene和value后,完成好了Individual类的建立了。

建立好了个体类型就需要确定如何给初始群体添加基因和计算适应度(也就是算出,该个体的值)。
解决这样的问题,可以通过建立函数的方式。
这里就建立两个函数,分别用于添加基因和计算适应度。
在建立好的工程图
上图是我建立好的工程,图中的define_var_for_ind是定义个体的基因的函数,函数内容如下图,图中定义了两个参数,一个是ind,是需要添加基因的个体;另一个是vbounds,表示函数每个变量的限制区间,函数体是一个循环,该循环是对每个基因赋予范围内的随机数,并且在最后返回添加的个体的基因:
在这里插入图片描述
图中还有一个函数叫get_value名字很直接,就是获得个体的值。这个函数只需要输入个体然后根据之前的目标函数算出函数值。
在这里插入图片描述

怎么实现遗传算法过程呢?

采用状态图,将算法过程看成是一个智能体。
然后建立一个智能体,选择a single agent,并且命名为ga_process.
在这里插入图片描述
双击进入,然后考虑整个过程是什么样的。
初始化群体→选择父代→杂交→变异→查看是否合法→循环产生足够的子代→循环产生足够的代数
然后画出来的状态图如下(这是已经建好的😊),下面这个智能体是已经建好的GA过程,最下面的三个是每一代的杂交、变异和判断基因的合法性的过程,它会一直循环到产生每代需要的足够的子代个数时才会跳出循环,进入上面的排序选择循环,上面的排序选择是在每代循环结束后执行的,执行到一定的代数以后就会跳出结束所有循环:
在这里插入图片描述
接下来的内容就按照状态流程图的过程进行介绍
首先,在statechart的Action中写入代码,为bestindividual初始化赋值,并且为初始化的best_individual的value赋值为无限大。
在这里插入图片描述
第一个状态是initialize_pop_s,进入该状态时会初始化一个群体并且储存在一个链表中(population),初始化群体的函数是inittialize_pop,使用函数需要两个参数,储存群体的链表和储存着变量范围的链表,然后根据变量的范围生成npop个数的有着范围内的基因个体。
在这里插入图片描述
接下来就进入了循环的状态(main_loop)在这里不进行任何操作,但是在它进入变迁的时候需要进行it+=1的操作,这是为了记住循环的子代代数,如果循环的子代代数足够就不再循环。
变迁后会进入一个branch在这个branch有三个出口:到达choose_parents、到达sort_s和到达结束状态。
这三个状态中,choose_parent是进行每代的交叉变异的过程,每次产生2个子代,当产生足够多的子代个数就跳出这一代的循环;sort_s是在每代结束后进行种群的排序选择的过程,淘汰最差的几个,使得种群数目保持不变;结束状态是当以上两种循环都结束以后就会进入结束状态。

交叉、变异与筛选超出边界子代

在图中的右下角的三个状态的变迁过程实现了以上的过程。
choose_parents 是通过轮盘赌法随机选择两个个体用来杂交:
如图下图中,先随机选出两个个体,然后将他们储存在一个链表里。
在这里插入图片描述
选择父代的方法是轮盘赌法,先根据每个个体的适应度算出每个个体被选择的概率,然后生成一个0到1的随机数,根据该随机数在累计概率的位置确定,选择的个体。
在这里插入图片描述
选择好交叉的父代以后就进行杂交,杂交后根据各自的基因计算每个个体的适应度,如下图是杂交的过程。
在这里插入图片描述
杂交的函数需要三个参数,杂交的父代和乘子。然后根据算数算子的公式对基因上的每一位进行计算,产生两个子代,然后储存在一个链表并返回出去。
在这里插入图片描述
杂交过后的子代会一定概率产生变异,mutate状态就是进行产生随机变异的状态。在下图中对产生的子代列表的个体进行遍历,依次进行变异→进行边界调整→获得变异调整后的个体的适应度→将个体添加到种群之中→如果个体的值比最优个体更为优秀则将最优个体换为该个体。遍历了整个子代个体后清空该列表,为下次过程准备。
在这里插入图片描述
变异函数如下,函数需要输入三个参数,变异个体(ind)、变异因子(gamma)和变异概率(mu)。变异采用随机确定,先生成一个列表储存一串0到1的随机数,每个随机数对应一个基因片段,并确定该基因是否变异,如果随机数小于mu就进行变异,由gamma乘以一个-0.5到0.5的随机数来改变基因片段,否则就不变。
在这里插入图片描述
边界调整是对超出边界的个体的基因做出调整,具体函数如下:
函数需要输入两个参数,调整的个体和参数的边界。对每个基因片段进行两个判断,是否大于最大边界,如果是就将其改为边界值,如果不是就不变;是否小于最小边界,如果是就改为最小边界,不是就不变。
在这里插入图片描述
最后在变迁的Action中将选择的父代链表清空,为下一次选择准备列表。

以上循环到产生的个体达到该子代要求的个数时,跳出循环,进入sorted状态。
sorted状态是对每代的群体进行选择,使得群体个数保持不变,并且筛选出不好的个体进行丢弃。
sort_f函数需要输入两个参数,群体和群体保留的个体的个数。该函数体的大致过程是,外部循环进行(群体个体个数-保留个数)每次循环找出最大的值丢弃,这样就保留了最优的个体。
在这里插入图片描述
以上就是算法的主要过程了,我将建立的模型上传到csdn上面了,如果感兴趣的,可以搜索一下。

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值