运用遗传算法求解函数极值(fortran)
运用遗传算法求解函数极值(fortran)
- 写在前面
- 遗传算法的前世今生
- 算法步骤简介
- 遗传算法的主体结构
- 开始求解:
- 结果显示:
- 最后再来说一些需要注意的地方
写在前面
这篇文章适合一些应急学习最优化算法的朋友们,对于大佬级别的同学请直接跳过,毕竟小编也只是一个和计算机没多大关系的传统工科生。
完整代码已经上传到本人博客资源,欢迎下载
小编第一次遇到遗传算法是在大三的一次美赛中,当时需要学习一些优化算法。然而作为最优化算法的远古级别的遗传算法自然是作为了我第一个学习的目标。
在这里写下我对GA的感觉,这个算法属于智能算法,理论上是可以实现全局最优但是经过一段时间的学习,感觉对于一些复杂的函数想实现全局最优还真的需要点运气。这个算法是最经典的,后期很多类似的算法纷纷出现,粒子群算法,蚁群算法之类的。这里不做评价,小编觉得学习其中一个就好,一通百通嘛。
最后!!!!!这次我用GA算法完整的计算了一些复杂的函数。这里给出一些关键步骤和一些心得以防自己后期回来温习。(ps完整代码后期有空传上去)
遗传算法的前世今生
遗传算法的概念最早是由Bagley J.D
于1967年提出的。后来Michigan大学的J.H.Holland教授于1975年开始对遗传算法(Genetic Algorithm,
GA)的机理进行系统化的研究。遗传算法是对达尔文生物进化理论的简单模拟,其遵循“适者生存”、“优胜略汰”的原理。遗传算法模拟一个人工种群的进化过程,并且通过选择、杂交以及变异等机制,种群经过若干代以后,总是达到最优(或近最优)的状态。自从遗传算法被提出以来,其得到了广泛的应用,特别是在函数优化、生产调度、模式识别、神经网络、自适应控制等领域,遗传算法更是发挥了重大的作用,大大提高了问题求解的效率。遗传算法也是当前“软计算”领域的重要研究课题。
本文首先结合fortran对遗传算法实现过程进行详细的分析,然后通过1个实际的函数优化案例对其应用进行探讨。
算法步骤简介
很多人都已经写过遗传算法的几个基本步骤,我在这里不做赘述,直接把地址放下来,大家可以去细细的品。这个算法原来这么神奇。
https://blog.csdn.net/qq_34374664/article/details/78874956
之前对我启发很大的博客找不到了,但是看完他的文章我相信你会对GA的大致过程有了一个了解
看完记得回来看我接下来的表演哦!
哈哈哈哈哈,是不是觉得竟然如此神奇,不需要多么强的数学理解能力就可以看懂。
遗传算法的主体结构
让我们开始遗传算法的编程环节
首先,我们需要整理一下思路想一下整个计算过程需要用到哪几个函数(子程序)
1.种群初始化
2.计算种群适应度
3.种群适应度排序
4.选择(筛选)操作
5.交叉操作
6.变异操作
以上是需要用到的函数。
其次,我们需要有一定的编大型程序的意识。对于一些数据可以设置为全局变量并且一直保存,所以我们需要提前把一些经常用到的量理出来。
pop_size: 输入种群大小
chromo_size: 输入染色体长度
generation_size: 输入迭代次数
cross_rate: 输入交叉概率
cross_rate: 输入变异概率
elitism: 输入是否精英选择
(这些变量在后面的用到的时候再作解释)
开始求解:
1.种群初始化:
integer i,j,k
integer pop_size, chromo_size,pop_num
real x
call RANDOM_SEED()
do i=1,pop_sizedo j=1,pop_numdo k=1,chromo_sizecall RANDOM_NUMBER(x)pop(i,j,k) = nint(x)end doend do
end do
语言解释:对大小为pop-size的种群的每个个体,对个体的pop-num个维度,对每个维度的chromo_size大小的染色体长度进行随机赋值。
RANDOM_SEED()__一个基本的随机数的产生函数
2.计算种群个体适应度(对不同的优化目标,此处需要改写)
integer i,j,kinteger pop_size,pop_num,chromo_sizereal fitness_value1(pop_size,pop_num).!do i=1,pop_size(单层维度,一个自变量时的初始化方法)
! fitness_value(i) = 0.
!end dodo i=1,pop_sizedo j=1,pop_numdo k=1,chromo_sizeif (pop(i,j,k) == 1)thenfitness_value1(i,j) = fitness_value1(i,j)+2**(k-1)end ifend do fitness_value1(i,j) = -500+fitness_value1(i,j)*(500-(-500))/(2**chromo_size-1)fitness_value1(i,j) = fitness_value1(i,j)*sin(sqrt(fitness_value1(i,j))) !***** *********更改函数fitness_value(i)=fitness_value1(i,j)+fitness_value(i)
end doend do
3.种群排序
对个体按适应度大小进行排序,并且保存最佳个体
integer pop_size,pop_num,chromo_size
integer i,j,k,m,min,temp
integer temp1(pop_num,chromo_size)do i=1,pop_size fitness_table(i) = 0.
end domin = 1
temp = 1
temp1(pop_num,chromo_size)=0do i=1,pop_sizemin = ido j = i+1,pop_size
if (fitness_value(j)<fitness_value(min))thenmin = j
end if
end do
if (min/=i)thentemp = fitness_value(i)fitness_value(i) = fitness_value(min)fitness_value(min) = temp
do m=1,pop_numdo k = 1,chromo_sizetemp1(m,k) = pop(i,m,k)pop(i,m,k) = pop(min,m,k)pop(min,m,k) = temp1(m,k)end do
end doend ifend dodo i=1,pop_size
if (i==1)thenfitness_table(i) = fitness_table(i) + fitness_value(i)
elsefitness_table(i) = fitness_table(i-1) + fitness_value(i)
end if
end do
!fitness_table!***********************????????????????
fitness_avg(G) = fitness_table(pop_size)/pop_sizeif (fitness_value(pop_size) > best_fitness)thenbest_fitness = fitness_value(pop_size)best_generation = G
end if
do i=1,pop_num
do j=1,chromo_sizebest_individual(i,j) = pop(pop_size,i,j)
end do
end do
4.轮盘赌选择操作
对于分布在“函数山”上不同的种群需要对劣势的种群进行处理。处理的规则是利用第三步中计算的函数适应度的大小作为每一个种群在轮盘上的分布角度大小。
然后转动轮盘,选中谁,谁就可以活下来。从中明显可得:对于低适应度的最小的种群最不可能被选上。
如果运气奇差,导致优秀的种群被排除,我们可以对这些优秀的种群采取“保送”的方式。(这里指的注意的是对这样保送的方式需要适可而止,防治局部最优)
integer pop_size, chromo_size,elitism,pop_num
integer i,j,k,p,r,mid,first,last,idx
real x,w,qcall RANDOM_SEED()
call RANDOM_NUMBER(x)
do i=1,pop_sizer = x * fitness_table(pop_size)first = 1last = pop_sizew=(last+first)/2mid = nint(w)idx = -1
do while ((first <= last).and.(idx == -1) )if (r > fitness_table(mid))thenfirst = mid
else if (r < fitness_table(mid))thenlast = mid
elseidx = mid
exit
end if
q=(last+first)/2mid = nint(q)if ((last - first) == 1)thenidx = lastexitend if
end do
do k=1,pop_numdo j=1,chromo_sizepop_new(i,k,j)=pop(idx,k,j)end do
end do
end do!**************************保送选择*************************
if (elitism==1)thenp = pop_size-1
elsep = pop_size
end if
do i=1,pdo k=1,pop_numdo j=1,chromo_sizepop(i,k,j) = pop_new(i,k,j)end do
end do
end do
5.单点交叉操作
implicit none
integer pop_size, chromo_size,cross_rate,pop_num
integer i,j,k,cross_pos,temp
real xcall RANDOM_SEED()
do i=1,pop_size,2do k=1,pop_numcall RANDOM_NUMBER(x)if(x < cross_rate)thencross_pos = nint(x * chromo_size) !交叉位置if(cross_pos == 0.or.cross_pos == 1)thencycleend ifdo j=cross_pos,chromo_sizetemp = pop(i,k,j)pop(i,k,j) = pop(i+1,k,j)pop(i+1,k,j) = tempend doend ifend do
end do
6.变异操作
!pop_size: 种群大小
!chromo_size: 染色体长度
!cross_rate: 变异概率
subroutine mutation(pop_size, chromo_size, mutate_rate,pop_num)
use a10
implicit none
integer i,j,mutate_pos
real x
integer pop_size, chromo_size,mutate_rate,pop_num
call RANDOM_SEED()do i=1,pop_sizedo j=1,pop_numcall RANDOM_NUMBER(x)if (x < mutate_rate)thenmutate_pos = nint(x*chromo_size)if (mutate_pos == 0)thencycleend ifpop(i,j,mutate_pos) = 1 - pop(i,j, mutate_pos)end ifend doend do
变异操作与交叉操作类似,但是其影响大小有区别。交叉操作相当于是函数山上的种群之间进行联谊以扩大它们之间的领土,清楚他们中间的位置盲区。他是相对可控制的。反观变异操作,则其就是随机的跳动,种群可能往更好的地方去,也可能去更差的地方。这需要读者自己修改参数以得到最优的结果。
至此,求解过程完成
结果显示:
这里原函数是。。。。。参考适应度计算里的更改函数的那一行,一个三十维度的函数。
下面是主程序:
program GA
use a10
implicit none
!real,external :: fitness***********还是用子程序好用
!integer,external:: rank
!real,external ::selection
!real,external :: crossover
!real,external :: mutationinteger m(30,24),p,j,i
real n,q(30)
integer,save::pop_size !种群大小
integer ,save::pop_num !单个种群维度
integer,save::chromo_size !染色体大小********** *********更改
integer ,save::elitism !选择精英操作
integer ,save::cross_rate !交叉概率
integer ,save::mutate_rate !变异概率!function [m,n,p,q] = GeneticAlgorithm(pop_size, chromo_size, generation_size, cross_rate, mutate_rate, elitism)
elitism = 1 !选择精英操作
pop_size = 1000 !种群大小
pop_num=30 !维度30
chromo_size = 24 !染色体大小
generation_size = 200 !迭代次数
cross_rate = 0.5 !交叉概率
mutate_rate = 0.01 !变异概率!print *, '开始了'fitness_avg = 0.fitness_value(pop_size) = 0.
best_fitness = 0.
best_generation = 0call initilize(pop_size,pop_num,chromo_size) !初始化do G=1,generation_size call fitness(pop_size,pop_num,chromo_size) !计算适应度 call rank(pop_size,pop_num,chromo_size) !对个体按适应度大小进行排序call selection(pop_size, chromo_size,elitism,pop_num) !选择操作call crossover(pop_size, chromo_size, cross_rate,pop_num) !交叉操作call mutation(pop_size, chromo_size, mutate_rate,pop_num) !变异操作
end do!**** ******************matlab中打印图像****************m = best_individual !获得最佳个体
n = best_fitness !获得最佳适应度
p = best_generation !获得最佳个体出现代!获得最佳个体变量值,对不同的优化目标,此处需要改写
q = 0.
do i=1,pop_num
do j=1,chromo_sizeif (best_individual(i,j) == 1)thenq(i)= q(i)+2**(j-1)end if
end do!!!!!!!!!!!!!!!!!*********************************更改为对应的自变量的值**********************q(i) = -500+q(i)*(500-(-500))/(2**chromo_size-1)
end dowrite(*,*)"最优个体"
write(*,*) m
write(*,*)"最优适应度"
write(*,*) n
write(*,*)"最优个体自变量"
write(*,*) q
write(*,*)"最优代数"
write(*,*) pend program GA
因为计算了很多函数没有及时保存最原始的一份,中间可能有点对应不上。但是大致思路都已经显示出来了
最后再来说一些需要注意的地方
- 需要了解二进制与十进制之间的转化。这里是运用插值的手法。
- 需要了解fortran中大型程序编写的模块化,以便于数据调用。
最后吧,时间有限,小编又比较懒,有空再来补充。以便于自己以后复习吧。
小编是水工结构的研究生,如果你读到这里了,大家可以多交流。
运用遗传算法求解函数极值(fortran)相关推荐
- 利用遗传算法求解函数极值
1.利用遗传算法求解函数极值 例1 利用遗传算法求函数 f(x) = 11sin(6x) + 7cos(5x),x∈[- π,π]的最大值点. 解:在MATLAB中编制绘制函数曲线的代码,运行得到题中 ...
- Python遗传算法求解函数极值
注:由于编码选择二进制编码,所以只能在整数范围进行搜索,也就是说求解到的最优解一定是最优的整数解,如果选择一些映射方法可以将离散问题连续化,但这样就和进化算法本身无关了,所以本文只写了基本的遗传算法 ...
- 人工智能遗传算法求函数极值
** 人工智能遗传算法求函数极值 ** 1.实验目的与原理 1)目的 熟悉和掌握遗传算法的原理.流程和编码策略,并利用遗传求解函数优化问题,理解求解函数极值问题的流程并测试主要参数对结果的影响,掌握遗 ...
- python求函数极值_python 遗传算法求函数极值的实现代码
废话不多说,大家直接看代码吧! """遗传算法实现求函数极大值-Zjh""" import numpy as np import rando ...
- <<人工智能导论>>上机--遗传算法求解函数最值
利用遗传算法求解函数 f(x,y)=1/(x2+y2+1),x,y∈[−5,5]f(x,y)=1/(x^2+y^2+1),x,y\in[-5,5]f(x,y)=1/(x2+y2+1),x,y∈[−5, ...
- 实值遗传算法求解函数极值问题(基于MATLAB)
实值遗传算法求解函数极值问题(基于MATLAB) 声明: 1.本文源代码来自书目<智能优化算法及其MATLAB实例(第3版)>,目的在于为MATLAB初学者提供更简明的代码解析,方便读者了 ...
- MATLAB求解函数极值及函数图像
MATLAB具有求解函数极值以及函数图像的功能,简单举一个例子. 求解上述函数极值与图像: 1.驻点求解 syms x >> y = (3*x^2 + 4*x +4)/(x^2 + x + ...
- 斐波那契(Fibonacci)迭代法求解函数极值(附代码)
目录 Fibonacci数列: 迭代公式: 算法步骤: 例题 C++代码: Fibonacci数列又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例 ...
- 爬山算法求解函数极值(matlab实现)
爬山算法: 爬山算法是一种简单的贪心搜索算法,在算法迭代的过程中,会从当前解的临近空间中随机选取下一个点,如果比当前结果好则会选取这个点作为新的最优解,否则再次进行选取.因为不是遍历得到的最优解,而是 ...
最新文章
- 如何筑起第二座“长城”?长城汽车:唯有科技
- 这些让人抓狂的烂代码,你碰到几种?
- AngularJS特性
- 关于“最终”的最终决定
- java中存在对多个对象加锁的情况_Java对象锁和类锁全面解析(多线程synchronized关键字)...
- Linux学习之旅(一)Linux常用命令
- 基于 CoreAudio 的音频编解码(一):音频解码
- 文章采集伪原创工具_伪原创文章技巧(如何提高伪原创文章的原创度)
- Shell脚本学习-阶段四-mysqladmin
- 浅析C++游戏开发工程师的工作职责以及任职资格
- cad2016中选择全图字体怎么操作_给几十页PPT换字体,我同事居然花了半个小时?明明3秒就能搞定...
- 面向对象编程 和 面向接口编程
- java面试题及答案2020 (二十五)
- golang怎么判断字符串是否为空
- uni-app广告总结
- SQL AND OR 运算符的用法
- Centos 7 | mariadb/mysql | [ERROR] InnoDB: Unable to lock ./ibdata1 error: 11
- ORACLE小写金额转大写金额
- 福特汉姆大学计算机科学专业,福特汉姆大学计算机与信息科学系
- Property dataSource threw exception