遗传算法求解y=x2 - 副本
- 格式:doc
- 大小:263.50 KB
- 文档页数:13
158EDUCATION FORUM 教育论坛摘要:微分方程在很多领域都有其重要性,为了求得微分方程的近似解,论文介绍了遗传算法思想及操作步骤,并给出了遗传算法求解常微分方程的过程,通过举例说明具体实现遗传算法解微分方程的步骤。
关键词:微分方程;遗传算法;最优化问题;近似解一、 前言实际生活中的各个方面的问题离不开函数关系,利用函数关系可以对客观事物的规律性进行研究,在实践中寻找函数关系至关重要。
很多实际问题在寻求函数关系时可以列出含有要找的函数及其导数的关系式,这样的关系式就是所谓微分方程。
17世纪初,牛顿、莱布尼兹和伯努利等科学家从几何和力学问题中分别建立了简单的微分方程,开创了微分方程的初期研究。
很多物理难题研究到一定程度都需要建立相应的数学模型,比如悬链线、共振现象的研究都归结于微分方程的求解问题,至此微分方程的研究变得很重要。
微分方程求解是微分方程问题中的核心,通过微分方程的解可以分析函数关系,并进行物理解释,从而预测物体发展规律,微分方程应用很广泛,在实际生活中的各个方面都能见到微分方程的应用,很多数学模型需要建立微分方程,设定初值条件,进行求解,研究解的特点和规律,为下一步分析和计划提供依据[1-2]。
微分方程分为常微分方程和偏微分方程,n 阶常微分方程的一般形式是:()(,,,,)n f x y y y ′= 0,[,]x a b ∈其中()n y 为y 的n 阶导数,边界条件由下式给出:()(,,,,)n i x t g x y y y −=′= 10,,,,i n 12其中t i =a 或t i =b 。
常微分方程求解是一个复杂的数学问题,方法虽然多,但实现起来比较困难,即使是一阶微分方程,求其精确解也是比较困难的,高阶微分方程的求解方法更复杂,很多微分方程很难求出其精确解,很多实际问题中我们可以找出它的近似解,在近似解达到一定近似程度的情况下,可以根据微分方程的近似解来分析解的性质和事物发展的规律。
遗传算法求函数最小值遗传算法是一种模拟自然界中生物进化过程的计算方法,其基本原理是模拟类比生物的自然选择、交叉和变异过程,以达到求解非线性优化问题的目的。
在本文中,我们将介绍如何使用遗传算法来求解一个简单但典型的非线性函数优化问题。
该函数是 Rosenbrock 函数,它是一个多峰函数,一般用来测试其他优化算法的性能。
Rosenbrock 函数的公式如下:$$f(x,y) = (1-x)^2 + 100(y-x^2)^2$$该函数有一个明显的最小值点 $(1, 1)$,函数值为 0。
我们的目标是使用遗传算法来找到这个最小值点。
以下是遗传算法的基本流程:1. 初始化种群:随机生成一组初始解。
2. 评估适应度:计算种群中每个解的适应度,即 Rosenbrock 函数的值。
适应度越高,表示该解越接近最小值点。
3. 选择育种个体:采用轮盘赌算法从种群中选择一些个体,用于后续的交叉和变异。
4. 交叉:对选择出来的个体进行交叉操作,生成一定数量的新个体。
交叉操作的目的是将两个个体的优良特征互相交换,以产生更好的后代。
5. 变异:对上一步生成的新个体进行变异操作,产生进一步的多样性和探索性。
6. 评估适应度:对新生成的个体进行适应度评估,即 Rosenbrock 函数的值。
7. 替换:选择一部分新生成的个体,替代原来种群中适应度低的个体。
8. 检查停止条件:判断是否满足停止条件,如果是,则输出最优解;否则回到第 3 步。
根据以上基本流程,我们可以逐步开发程序实现。
首先,我们定义一个 Rosenbrock 函数的计算函数:```pythondef rosenbrock(x, y):return (1 - x)**2 + 100*(y - x**2)**2```然后,我们随机生成一组初始解,使用 numpy 库生成随机数,x、y 取值范围在 [-3,3]:```pythonimport numpy as npPOPULATION_SIZE = 100 # 种群大小BOUND_LOW, BOUND_HIGH = -3.0, 3.0 # 取值范围populations = np.random.uniform(low=BOUND_LOW, high=BOUND_HIGH,size=(POPULATION_SIZE, 2))```fitness = [rosenbrock(x, y) for x, y in populations]df = pd.DataFrame({'x': populations[:, 0], 'y': populations[:, 1],'fitness': fitness})```然后,我们编写轮盘赌算法选择育种个体的代码。
遗传算法遗传算法是一种借鉴生物遗传和进化机制寻求最优解的计算方法。
该方法模拟生物进化中的复制、交换、变异等过程,并通过模拟自然选择压力的方式推动问题解集向最优解方向移动。
遗传算法为解决多种难以采用传统数学方法求解的复杂问题提供了新的思路。
1. 遗传算法的发展历史研究者采用计算机模拟生物进化过程并解决优化问题的尝试始于20世纪40至50年代。
20世纪60年代中期,美国密歇根大学的Holland教授提出了位串编码技术,这种编码技术适用于变异操作和交叉操作,他指出在研究和设计人工自适应系统时可借鉴生物遗传的机制,以群体的方式进行自适应搜索。
70年代中期,Holland提出遗传算法的模式定理(Schema Theorem),奠定了遗传算法的理论基础。
11967年,Holland教授的学生De Jong首次将遗传算法应用于函数优化中,2设计了遗传算法执行策略和性能评价指标。
他挑选的5个专门用于遗传算法数值实验的函数至今仍被频繁使用,而他提出的在线(on-line)和离线(off-line)指标则仍是目前衡量遗传算法优化性能的主要手段。
1989年,Goldberg出版专著“Genetic Algorithm in Search, Optimization, and Machine learning”3。
该书全面阐述了遗传算法的基本原理及应用,并系统总结了遗传算法的主要研究成果。
该书对遗传算法科学基础的奠定做出了重要贡献。
1991年,Davis编辑出版了专著“Handbook of Genetic Algorithms”,该书中介绍了遗传算法在工程技术和社会生活中的大量应用实例。
41992年,美国斯坦福大学的Koza出版专著“Genetic Programming, on the Programming of Computers by Means of Natural Selection”,在此书中,他将遗传算法应用于计算机程序的优化设计和自动生成,并在此基础上提出遗传编程(Genetic Programming, GP)的概念5。
2.遗传算法随着优化理论的发展,一些新的智能算法得到了迅速发展和广泛应用,成为解决传统系统辨识问题的新方法,如遗传算法、蚁群算法、粒子群算法、差分进化算法等。
这些算法丰富了系统辨识技术,这些优化算法都是通过模拟揭示自然现象和过程来实现的,其优点和机制的独特,为具有非线性系统的辨识问题提供了切实可行的解决方案。
本章介绍遗传算法解决参数辨识问题。
2.1 遗传算法的基本原理遗传算法简称GA(Genetic Algorithms),是1962年由美国密歇根大学Holland 教授提出的模拟自然界遗传机制和生物进化论而成的一种并行随机搜索最优化方法。
遗传算法是以达尔文的自然选择学说为基础发展起来的。
自然学说包括以下3个方面。
(1)遗传这是生物的普遍特征,亲代把生物信息交给子代,子代按照所得信息而发育、分化,因而下代总是和亲代具有相同或相似的性状。
生物有了这个特征,物种才能稳定存在。
(2)变异亲代和子代之间及子代的不同个体之间总有些差异,这种现象成为变异。
变异是随机发生的,变异的选择和积累是生命多样性的根源。
(3)生存斗争和适者生存自然选择来自繁殖过剩和生存斗争。
由于弱肉强食的生存斗争不断的进行,其结果是适者生存,既具有适用性变异的个体被保存下来,不具有适应性变异的个体被淘汰,通过一代代的生存环境的选择作用,性状逐渐与祖先有所不同,演变为新的物种。
这种自然选择是一个长期的、缓慢的、连续的过程。
遗传算法将“优胜劣汰,适者生存”的生物进化原理引入优化参数形成的编码串联群体中,按所选择的适配值函数并通过遗传中复制、交叉以及变异对个体进行筛选,使适配值高的个体被保留下来,组成新的群体,新的群体既继承了上一代的信息,又优于上一代。
这样周而复始,群体中个体适应度不断提高,直到满足一定的条件。
遗传算法的算法简单,可并行处理,并能得到全局最优解。
遗传算法的基本操作分为如下三种:(1)复制(Reproduction Operator)复制是从一个旧种群中选择生命力强的个体位串产生新种群的过程。
一、介绍Matlab是一个高性能的数学计算软件,它集成了许多数学工具箱,其中包括遗传算法工具箱,可以帮助用户利用遗传算法求解最优化问题。
遗传算法是一种模拟生物进化过程的优化方法,通过模拟自然选择、交叉和变异等操作,不断优化解的搜索空间,从而找到最优解。
二、遗传算法求最大值步骤1. 创建遗传算法对象我们需要使用Matlab的遗传算法工具箱中的函数`ga`来创建一个遗传算法对象。
在创建对象时,需要指定优化的目标函数、决策变量的上下界、约束条件等参数,以及遗传算法的种裙大小、进化代数等参数。
例如:```matlaboptions = gaoptimset('Generations', 100, 'PopulationSize', 50); [x, fval, exitflag, output] = ga(fitnessfun, nvars, A, b, Aeq, beq, lb, ub, nonlcon, options);```其中,`fitnessfun`是用户自定义的目标函数,`nvars`是决策变量的个数,`A`, `b`, `Aeq`, `beq`是线性约束条件,`lb`, `ub`是决策变量的上下界,`nonlcon`是非线性约束条件,`options`是遗传算法的参数设置。
2. 编写目标函数用户需要编写自己的目标函数`fitnessfun`,该函数接受决策变量作为输入,并返回一个标量作为目标值。
例如:```matlabfunction y = fitnessfun(x)y = -sum(x.^2);end```在这个例子中,我们希望求解一个多维的最大化问题,因此目标函数返回了决策变量的负平方和作为最优解的评价指标。
3. 运行遗传算法一切准备就绪后,我们可以调用`ga`函数来运行遗传算法,并获取最优解和最优值。
遗传算法会不断进化种裙,直到达到指定的进化代数为止。
matlab遗传算法整数约束遗传算法是一种通过模拟进化过程来解决优化问题的算法。
在许多实际问题中,我们需要找到满足一定约束条件的整数解。
本文将介绍如何使用MATLAB编程语言实现遗传算法,并给出一个整数约束的示例问题。
我们需要定义问题的目标函数和约束条件。
假设我们要求解的问题是在一定范围内找到使得目标函数取得最大值的整数解。
目标函数可以是任意的数学函数,如线性函数、非线性函数等。
约束条件可以包括等式约束和不等式约束,限制了解的取值范围。
接下来,我们需要定义遗传算法的基本元素,包括染色体表示、初始化种群、适应度评价、选择、交叉和变异等操作。
对于整数约束问题,染色体可以用一个整数数组表示,每个元素对应一个变量的取值。
种群可以由多个染色体组成,初始种群可以通过随机生成整数数组来实现。
适应度评价可以通过计算目标函数值来衡量染色体的优劣。
选择操作可以根据适应度值来确定优秀染色体的概率选择。
交叉操作可以通过交换染色体的某些片段来产生新的染色体。
变异操作可以通过改变染色体中的某个元素值来引入新的解。
在MATLAB中,我们可以使用遗传算法工具箱来实现遗传算法。
首先,我们需要定义一个函数来描述问题的目标函数和约束条件。
然后,我们可以使用`ga`函数来求解整数约束问题。
该函数的输入参数包括目标函数、变量的取值范围、约束条件等。
通过设置适当的参数,我们可以控制遗传算法的执行过程。
下面,我们以一个简单的整数约束问题为例进行演示。
假设我们要求解的问题是在区间[0, 10]内找到使得函数f(x) = x^2取得最大值的整数解。
我们可以定义目标函数和约束条件如下:```matlabfunction y = myfun(x)y = -x.^2; % 目标函数,取负号使得求解最大值问题endfunction [c, ceq] = mycon(x)c = []; % 不等式约束条件ceq = []; % 等式约束条件end```然后,我们可以使用遗传算法工具箱中的`ga`函数来求解整数约束问题:```matlablb = 0; % 变量下界ub = 10; % 变量上界intcon = 1; % 整数约束[x, fval] = ga(@myfun, 1, [], [], [], [], lb, ub, @mycon, intcon); ```以上代码中,`@myfun`表示目标函数,`1`表示变量的个数,`[]`表示不等式约束条件,`lb`和`ub`表示变量的下界和上界,`@mycon`表示约束条件,`intcon`表示整数约束。
遗传算法求解函数最小值1. 引言遗传算法是一种基于生物进化原理的优化算法,可以用来求解函数的最小值。
在实际问题中,很多优化问题可以转化为函数极值问题。
遗传算法通过模拟自然进化过程,逐步搜索得到最优解。
本文将详细介绍遗传算法求解函数最小值的定义、用途和工作方式等内容,并通过一个具体的例子进行演示。
2. 函数的定义在数学中,函数是一种特殊的关系,它将一个或多个输入映射到唯一的输出。
对于连续可导的函数而言,通常可以通过计算导数找到其极值点。
但对于复杂、非线性或无法直接计算导数的函数,如黑箱函数等,传统的方法可能不适用。
在这种情况下,遗传算法可以作为一种有效的方法来搜索函数中的最小值。
遗传算法通过构建和演化一组候选解来逐步逼近最优解。
3. 遗传算法求解函数最小值的用途遗传算法广泛应用于各个领域中需要求解优化问题的场景。
在工程、经济学、物理学等领域中,很多实际问题可以形式化为函数最小值问题。
例如,在机器学习中,通过最小化损失函数来优化模型的参数;在路径规划中,通过最小化成本函数来找到最短路径。
遗传算法的优势在于其可以处理复杂、非线性和高维的函数空间。
相比传统的优化算法,遗传算法具有更好的全局搜索能力和对噪声的鲁棒性。
4. 遗传算法求解函数最小值的工作方式遗传算法主要由以下几个步骤组成:初始化种群、选择操作、交叉操作、变异操作和停止准则。
下面将详细介绍每个步骤的具体工作方式。
4.1 初始化种群首先,需要随机生成一组候选解作为初始种群。
这些候选解通常用二进制编码表示,并称为个体。
4.2 选择操作选择操作是根据个体适应度(即目标函数值)进行选择,使得适应度较高的个体有更大的概率被选中。
常见的选择方法有轮盘赌选择、锦标赛选择等。
4.3 交叉操作交叉操作模拟生物进化中的基因交换过程。
通过随机选择一对个体,将它们的某一部分基因进行交换,产生新的个体。
交叉操作可以增加种群的多样性,并加速搜索过程。
4.4 变异操作变异操作模拟生物进化中的基因突变过程。
遗传算法公式遗传算法是一种优化算法,它模拟了生物进化中的遗传过程,通过不断迭代和优化,寻找最佳的解决方案。
遗传算法的核心是基因编码和遗传操作。
在遗传算法中,每个解决方案都被看作是一个个体,而每个个体都具有一组基因,这些基因决定了个体的特征和性能。
为了优化问题,遗传算法会对这些基因进行遗传操作,包括选择、交叉和变异,以产生更好的后代。
在本文中,我们将介绍遗传算法的公式和应用。
基因编码在遗传算法中,每个个体都被编码为一个染色体,而染色体则由一组基因组成。
基因编码可以采用不同的方式,包括二进制编码、实数编码和排列编码等。
其中,二进制编码是最常用的一种方式,它将个体的每个基因都表示为一个二进制位,0表示基因不存在,1表示基因存在。
例如,假设我们要优化一个问题,其中每个解决方案都由4个变量组成,分别是x1、x2、x3和x4,而这些变量的取值范围都在[0,1]之间。
则我们可以将每个变量都用10位二进制数来表示,例如,x1=0.1011010110,x2=0.0010100011,x3=0.1100111010,x4=0.0111100101。
这样,每个个体就可以用一个40位的二进制串来表示。
选择操作选择操作是遗传算法中的基本操作之一,它的目的是从当前种群中选出一部分个体,作为下一代种群的父代。
选择操作通常根据个体的适应度值来进行,适应度值越高的个体被选中的概率就越大。
在遗传算法中,适应度值通常由目标函数来计算,目标函数的值越小,个体的适应度值就越高。
选择操作可以采用多种方式,包括轮盘赌选择、竞标选择和锦标赛选择等。
其中,轮盘赌选择是最常用的一种方式,它的原理是根据个体的适应度值来分配一个相对概率,然后随机选择一个个体作为父代。
具体来说,假设当前种群中有N个个体,每个个体的适应度值为f(i),则个体i被选中的概率可以用下面的公式来计算:P(i)=f(i)/Σf(j)其中,Σf(j)表示当前种群中所有个体的适应度值之和。
初始遗传算法及一个简单的例子遗传算法(Genetic Algorithms, GA)是一类借鉴生物界自然选择和自然遗传机制的随机化搜索算法。
它模拟自然选择和自然遗传过程中发生的繁殖、交叉和基因突变现象,在每次迭代中都保留一组候选解,并按某种指标从解群中选取较优的个体,利用遗传算子(选择、交叉和变异)对这些个体进行组合,产生新一代的候选解群,重复此过程,直到满足某种收敛指标为止。
下面我以一个实例来详细表述遗传算法的过程例:求下述二元函数的最大值:2=]y xx∈,0[311、编码:用遗传算法求解问题时,不是对所求解问题的实际决策变量直接进行操作,而是对表示可行解的个体编码的操作,不断搜索出适应度较高的个体,并在群体中增加其数量,最终寻找到问题的最优解或近似最优解。
因此,必须建立问题的可行解的实际表示和遗传算法的染色体位串结构之间的联系。
在遗传算法中,把一个问题的可行解从其解空间转换到遗传算法所能处理的搜索空间的转换方法称之为编码。
反之,个体从搜索空间的基因型变换到解空间的表现型的方法称之为解码方法。
编码是应用遗传算法是需要解决的首要问题,也是一个关键步骤。
迄今为止人们已经设计出了许多种不同的编码方法。
基本遗传算法使用的是二进制符号0和1所组成的二进制符号集{0,1},也就是说,把问题空间的参数表示为基于字符集{0,1}构成的染色体位串。
每个个体的染色体中所包含的数字的个数L 称为染色体的长度或称为符号串的长度。
一般染色体的长度L为一固定的数,如本例的编码为s1 = 1 0 0 1 0 (17)s2 = 1 1 1 1 0 (30)s3 = 1 0 1 0 1 (21)s4 = 0 0 1 0 0 (4)表示四个个体,该个体的染色体长度L=5。
2、个体适应度函数在遗传算法中,根据个体适应度的大小来确定该个体在选择操作中被选定的概率。
个体的适应度越大,该个体被遗传到下一代的概率也越大;反之,个体的适应度越小,该个体被遗传到下一代的概率也越小。
基本遗传算法使用比例选择操作方法来确定群体中各个个体是否有可能遗传到下一代群体中。
为了正确计算不同情况下各个个体的选择概率,要求所有个体的适应度必须为正数或为零,不能是负数。
这样,根据不同种类的问题,必须预先确定好由目标函数值到个体适应度之间的转换规则,特别是要预先确定好目标函数值为负数时的处理方法。
如所求解的问题为:)(max f 直接设定个体的适应度函数值就等于相应的目标函数值,即2)(f x x =. 3、遗传算子 (1)比例选择:选择或称复制,建立在对个体适应度进行评价的基础之上。
其作用是从当前群体中选择出一些比较优良的个体,并将其复制到下一代群体中。
基本遗传算法采用比例选择的方法,所谓比例选择,是指个体在选择操作中被选中的概率与该个体的适应度大小成正比。
本例选择概率的计算公式为:∑==n j j s f s f 1i i )()(p其中f 为适度函数;)(i s f 为个体i s 的适应值,显然,适应值最高的个体被随机选定的概率就越大,被选择的次数就越多,从而被繁殖的次数也就越多。
(2)单点交叉。
单点交叉又称简单交叉,是遗传算法所使用的交叉操作方法。
选择一个交叉点,子代在交叉点前面的基因从一个父代基因那里得到,后面的部分从另外一个父代基因那里得到。
如:交叉前: 100|10101|01交叉后: 100|01101|10(3)基本位变异。
基本位变异石最简单和最基本的变异操作,也是基本遗传算法中所使用的变异操作方法。
对于基本遗传算法中用二进制编码符号串所表示的个体,对需要进行变异操作的某一基因,若原有基因值为0,则变异操作将该基因值变为1;反之,若原有基因值为1,则变异操作将其变为0.基本位变异算子是指对个体编码串随机指定的某一位或某几位基因作变异运算。
对于基本遗传算法中用二进制编码符号串所表示的个体,若需要进行变异操作的某一基因座上的原有基因值为0,则变异操作将其变为1;反之,若原有基因值为1,则变异操作将其变为0。
如:变异前:1001|0变异后:1001|1(4)基本遗传算法的运行参数本例中指定四个基本参数种群大小:popsize最大世代数 maxgeneration交叉率pc变异率pm至于遗传算法的终止条件,还可以利用某种判定准则,当判定出群体已经进化成熟且不再有进化趋势时就可终止算法的运行过程。
如连续几代个体平均适应度的差异小于某一个极小的值;或者群体中所有个体适应度的方差小于某一个极小的值。
这4个参数对遗传算法的搜索结果及搜索效率都有一定的影响,目前尚无合理选择它们的理论根据在遗传算法的实际应用中,往往需要经过多次的试算后才能确定出这些参数合理的取值范围或取值大小4、遗传算法的应用步骤如下:遗传算法提供了一种求解复杂系统优化问题的通用框架,它不依赖于问题的领域和种类。
对一个需要进行优化计算的实际应用问题,一般可按下述步骤来构造求解该问题的遗传算法。
第一步:建立优化模型,即确定出目标函数、决策变量及各种约束条件以及数学描述形式或量化方法。
第二步:确定表示可行解的染色体编码方法,也即确定出个体的基因型x及遗传算法的搜索空间。
第三步:确定解码方法,即确定出个体基因型x到个体表现型x的对应关系或转换方法。
第四步:确定个体适应度的量化评价方法,即确定出由目标函数值)(f x到个体适应度)x(F的转换规则。
第五步:设计遗传操作方法,即确定出选择运算、交叉运算、变异运算等具体操作方法。
第六步:确定遗传算法的有关运行参数,即确定出遗传算法的种群大小(popsize)、最大世代数 (maxgeneration)、交叉率(pc)、变异率(pm)等参数。
由上述构造步骤可以看出,可行解的编码方法、遗传操作的设计是构造遗传算法时需要考虑的两个主要问题,也是设计遗传算法时的两个关键步骤。
对不同的优化问题需要使用不同的编码方法和不同的遗传操作,它们与所求解的具体问题密切相关,因而对所求解问题的理解程度是遗传算法应用成功与否的关键。
本例c语言代码//////////////////////////////////////遗传算法解决 y=x2问题//编译环境 vc++6.0//声明:部分代码来自网#include <stdio.h>#include<stdlib.h>#include<time.h>#include<math.h>#define POPSIZE 500 //种群大小#define chromlength 5 //染色体长int popsize ; //种群大小int maxgeneration; //最大世代数double pc = 0.0; //交叉率double pm = 0.0; //变异率struct individual //定义染色体个体结构体{int chrom[chromlength]; //定义染色体二进制表达形式,edit by ppme 将char 转为 intdouble value; //染色体的值double fitness; //染色体的适应值};int generation; //当前执行的世代数int best_index; //最好的染色体索引序号int worst_index; //最差的染色体索引序号struct individual bestindividual; //最佳染色体个体struct individual worstindividual; //最差染色体个体struct individual currentbest; //当前最好的染色体个体 currentbest struct individual population[POPSIZE];//种群数组//函数声明void generateinitialpopulation(); //ok-初始化当代种群void generatenextpopulation(); //产生下一代种群void evaluatepopulation(); //评价种群void calculateobjectfitness(); //计算种群适应度double decodechromosome(int,int); //染色体解码void findbestandworstindividual(); //寻找最好的和最坏的染色体个体void performevolution(); //进行演变进化void selectoperator(); //选择操作void crossoveroperator(); //交换操作void mutationoperator(); //变异操作void input(); //输入接口void outputtextreport(); //输出文字报告void main() //主函数{int i;srand((unsigned)time(NULL)); //强制类型转化,以当前时间戳定义随机数种子printf("本程序为求函数y=x*x的最大值\n");generation=0; //初始化generation当前执行的代input(); //初始化种群大小、交叉率、变异率/*edit by ppme*///调试用。
显示input()结果printf("种群规模(popsize): %d;\n最大世代数(maxgeneration) %d;\n交叉率(pc) %f;变异率(pm) %f\n\n",popsize,maxgeneration,pc,pm);/*edit by ppme*/generateinitialpopulation(); //产生初始化种群evaluatepopulation(); //评价当前种群,(A.计算种群/个体的适应度;B.找出最好和最差的个体)while(generation<maxgeneration) //小于最大世代数,执行循环体{generation++;generatenextpopulation(); //生成子代种群(A.选择; B.交叉; C.变异)evaluatepopulation(); //评价新生子代种群performevolution(); //进行子代进化outputtextreport(); //输入当代最终种群}printf("\n");printf(" 统计结果: ");printf("\n");printf("最大函数值等于:%f\n",currentbest.fitness);printf("其染色体编码为:");//计算currentbest的valuefor( i = 0 ; i < chromlength ; i++ )printf(" %d",currentbest.chrom[i]);printf("\n");}void generateinitialpopulation( ) //种群初始化{int i,j;srand((unsigned)time(NULL)); //强制类型转化,以当前时间戳定义随机数种子for (i=0;i<popsize; i++){for(j=0;j<chromlength;j++){population[i].chrom[j]=(rand()%10<5)?0:1; //rand()%10随机产生0-9的整数//,小于5标注0,否则标注1}}//调试显示初始化结果printf("显示初始化结果:\n");for(i = 0 ; i < popsize ; i++){for(j = 0 ; j < chromlength ; j++){printf(" %d",population[i].chrom[j]);}printf("\n");}}void generatenextpopulation() //生成下一代{selectoperator();crossoveroperator();mutationoperator();}void evaluatepopulation() //评价种群???{calculateobjectfitness(); //计算种群?个体的适应度findbestandworstindividual(); //赵到最好和最差的染色体个体}void calculateobjectfitness() //计算染色体个体适应值和适应度{int i;int j;printf("calculateobjectfitness is executing!\n");for(i=0;i<popsize;i++){double temp;temp=decodechromosome(i,chromlength); //计算个体适应值population[i].value=(double)temp;population[i].fitness=population[i].value*population[i].value;}//调试用printf("显示当前种群结果:\n");for(i = 0 ; i < popsize ; i++){for(j = 0 ; j < chromlength ; j++){printf(" %d",population[i].chrom[j]);}printf(" %lf",population[i].value);printf(" %lf",population[i].fitness);printf("\n");}}double decodechromosome(int pop_index , int length) //给染色体解码{int i;double decimal=0;for( i = length; i >= 0 ; i-- )decimal += population[pop_index].chrom[i]*pow(2,i); //遍历染色体二进制编码,return (decimal); //并计算出其10进制的value值}void findbestandworstindividual( ) //求最佳个体和最差个体{int i;double sum=0.0;bestindividual=population[0];worstindividual=population[0];for (i=1;i<popsize; i++){if (population[i].fitness>bestindividual.fitness) //依次比较,找出最佳个体{bestindividual=population[i];best_index=i;}else if (population[i].fitness<worstindividual.fitness) //依次比较,找出最差个体{worstindividual=population[i];worst_index=i;}sum+=population[i].fitness; //sum 存放种群总体适应值}//forif (generation==0){currentbest=bestindividual; //第一代最好的暂时存放在currentbest}else{if(bestindividual.fitness>=currentbest.fitness)//第n代最好的,通过比较大于以往最好个体的话,{ //暂时存放在currentbestcurrentbest=bestindividual;}}}void performevolution() //演示评价结果{if (bestindividual.fitness>currentbest.fitness){currentbest=population[best_index];}else{population[worst_index]=currentbest;}}void selectoperator() //比例选择算法{int i,index;double p,sum=0.0; //p存放随机概率,sum存放个体适应率和累计适应率double cfitness[POPSIZE]; //当代种群染色体个体的适应率struct individual newpopulation[POPSIZE]; //新种群srand((unsigned) time(NULL)); //种下随机种子for(i=0;i<popsize;i++) //{sum+=population[i].fitness; //sum存放种群适应值总和}for(i=0;i<popsize; i++){cfitness[i]=population[i].fitness/sum; // cfitness[] = fitness/sum得到个体适应率}for(i=1;i<popsize; i++){cfitness[i]=cfitness[i-1]+cfitness[i]; //cfitness[]= cfitness[i-1]+cfitness[i]得到种群} //累计适应率for (i=0;i<popsize;i++) //for循环实现轮盘赌算法{p=rand()%1000/1000.0; //得到千分位小数index=0;while (p>cfitness[index]){index++;}newpopulation[i]=population[index]; //选出的个体组成新的一代,暂时存放于newpopulation[]中}for(i=0;i<popsize; i++){population[i]=newpopulation[i]; //全局变量populaiton存放新的种群(有重复的值)}}void crossoveroperator() //交叉算法{int i,j;int index[POPSIZE];int point,temp;double p;srand((unsigned) time(NULL)); //种下随机种子for (i=0;i<popsize;i++){ //初始化index[]数组index[i]=i;}for (i=0;i<popsize;i++){ //for 循环实现种群内随机两两交换point=rand()%(popsize-i); //打乱种群顺序temp=index[i];index[i]=index[point+i];index[point+i]=temp;}for (i=0;i<popsize-1;i+=2){p=rand()%1000/1000.0;if (p<pc){ //单点交叉算法point=rand()%(chromlength-1)+1;for (j=point; j<chromlength;j++){temp=population[index[i]].chrom[j];population[index[i]].chrom[j]=population[index[i+1]].chrom[j];population[index[i+1]].chrom[j]=temp;}}}}void mutationoperator() //变异操作{int i,j;double p;srand((unsigned) time(NULL)); //种下随机种子for (i=0;i<popsize;i++){for(j=0;j<chromlength;j++){p=rand()%1000/1000.0;if (p<pm){population[i].chrom[j]=(population[i].chrom[j]==0)?1:0;}}}}void input() //数据输入{printf("初始化全局变量:\n");printf("种群大小(4-500偶数):");scanf("%d", &popsize); //输入种群大小,必须为偶数if((popsize%2) != 0){printf("种群大小已设置为偶数\n");popsize++;};printf("最大世代数(10-300):"); //输入最大世代数scanf("%d", &maxgeneration);printf("交叉率(0.2-1.0):"); //输入交叉率scanf("%lf", &pc);printf("变异率(0.00):"); //输入变异率scanf("%lf", &pm);}void outputtextreport()//数据输出{int i;double sum;double average;sum=0.0;for(i=0;i<popsize;i++){sum+=population[i].value;}average=sum/popsize;printf("当前世代=%d\n当前世代染色体平均值=%f\n当前世代染色体最高值=%f\n",generation,average,population[best_index].value);}运行结果:/*本程序为求函数y=x*x的最大值初始化全局变量:种群大小(4-500偶数):4最大世代数(10-300):5交叉率(0.2-1.0):0.9变异率(0.00):0.01种群规模(popsize): 4;最大世代数(maxgeneration) 5;交叉率(pc) 0.900000;变异率(pm) 0.010000显示初始化结果:0 1 0 0 11 1 1 1 10 0 0 1 00 1 1 1 1calculateobjectfitness is executing!显示当前种群结果:0 1 0 0 1 18.000000 324.0000001 1 1 1 1 31.000000 961.0000000 0 0 1 0 8.000000 64.0000000 1 1 1 1 30.000000 900.000000 calculateobjectfitness is executing!显示当前种群结果:1 1 1 1 1 31.000000 961.0000000 1 0 0 1 18.000000 324.0000000 1 0 0 1 18.000000 324.0000001 1 1 1 1 31.000000 961.000000当前世代=1当前世代染色体平均值=27.750000当前世代染色体最高值=31.000000 calculateobjectfitness is executing!显示当前种群结果:1 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.000000当前世代=2当前世代染色体平均值=31.000000当前世代染色体最高值=31.000000 calculateobjectfitness is executing!显示当前种群结果:1 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.000000当前世代=3当前世代染色体平均值=31.000000当前世代染色体最高值=31.000000 calculateobjectfitness is executing! 显示当前种群结果:1 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.000000当前世代=4当前世代染色体平均值=31.000000当前世代染色体最高值=31.000000 calculateobjectfitness is executing! 显示当前种群结果:1 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.0000001 1 1 1 1 31.000000 961.000000当前世代=5当前世代染色体平均值=31.000000当前世代染色体最高值=31.000000统计结果:最大函数值等于:961.000000其染色体编码为: 1 1 1 1 1Press any key to continue*/。