遗传算法python实现_python实现遗传算法样例

本文介绍了一种无约束优化算法——遗传算法,并提供了一个Python实现样例。该算法通过模拟自然界中的遗传过程来寻找最优解,包括选择、交叉和变异等操作。

一直想写一个遗传算法的样例,正好最近有空,写了一个。

遗传算法是一种无约束优化算法,借鉴了遗传理论,从一组初始点开始,计算目标函数,然后根据计算结果,对初始点进行交叉和变异操作,获得一组新的点。这一组新获得的点平均值优于初始点。如此往复迭代,直到达到所需要的精度为止。

遗传算法的步骤如下:

1. 令k=0,产生一个初始种群P(0)

2. 评估P(k),计算P(k)中每个个体的适应度

3. 如果满足停止规则,停止迭代

4. 从P(k)中选择新种群M(k)

5. 进化M(k),构成新种群P(k+1)

6. 令k=k+1,回到第2步

下面给出样例代码:

GenericAlgorithm.py

# -*- coding: utf-8 -*-

import numpy

# 遗传算法求最大值

class GenericAlgorithm:

# func为要求最大值的函数

# encoding决定是否对自变量进行编码

# min为args对应最小值

# max为args对应最大值

# dnaLength为dna编码长度

def __init__(self, func, min, max, encoding = False, dnaLength = 128):

self._func = func

self._min = min

self._max = max

self._flag = encoding

self._dnaLen = dnaLength

def __del__(self):

return

# 编码,仅在交叉和变异时使用,此处用最简单的二进制编码

def _encode(self, matrix, length):

rows = matrix.shape[0]

columns = matrix.shape[1]

realen = int(length / columns)

bmax = 2**(realen) - 1

r = [self._max[i] - self._min[i] for i in range(len(self._min))]

mkb = []

for i in range(rows):

tmp = ''

for j in range(columns):

bstr = str(bin(int((matrix[i][j] - self._min[j])/r[j] * bmax)))

bstr = bstr[2:].zfill(realen)

tmp += bstr

mkb.append(tmp)

return mkb

# 解码,同上

def _decode(self, matrix, length):

rows = len(matrix)

columns = len(self._min)

realen = int(length / columns)

bmax = float(2**(realen) - 1)

r = [self._max[i] - self._min[i] for i in range(len(self._min))]

mk = numpy.zeros((rows, columns))

for i in range(rows):

for j in range(columns):

tmp = matrix[i][j*realen:(j+1)*realen]

mk[i][j] = int(tmp,2) / bmax * r[j] + self._min[j]

return mk

def _evolve(self, mk, prop_cross, prop_mut):

mk = self._cross(mk, prop_cross)

pk = self._mutation(mk, prop_mut)

return pk

# 交叉

def _cross(self, mk, prop_cross):

rows = mk.shape[0]

columns = mk.shape[1]

idx = numpy.zeros(1)

while (idx.shape[0] % 2 != 0):

idx = numpy.where(numpy.random.rand(rows,1) < prop_cross)[0]

if (self._flag):

mkb = self._encode(mk, self._dnaLen)

for i in range(0, idx.shape[0], 2):

bit = int(numpy.random.rand()*self._dnaLen)

tmp1 = mkb[idx[i]][:bit] + mkb[idx[i+1]][bit:]

tmp2 = mkb[idx[i+1]][:bit] + mkb[idx[i]][bit:]

mkb[idx[i]] = tmp1

mkb[idx[i+1]] = tmp2

mk = mkb

else:

for i in range(0, idx.shape[0], 2):

rn = numpy.random.rand()

w = numpy.random.randn(1,columns)

tmp1 = rn*mk[idx[i]] + (1-rn)*mk[idx[i+1]] + w

tmp2 = (1-rn)*mk[idx[i]] + rn*mk[idx[i+1]] - w

mk[idx[i]] = tmp1

mk[idx[i+1]] = tmp2

for i in range(rows):

for j in range(columns):

mk[i][j] = numpy.clip(mk[i][j], self._min[j], self._max[j])

return mk

# 变异

def _mutation(self, mk, prop_mut):

if (self._flag):

rows = len(mk)

for i in range(rows):

tmp = list(mk[i])

idx = numpy.where(numpy.random.rand(self._dnaLen) < prop_mut)[0]

for j in range(len(idx)):

if (tmp[idx[j]] == '0'):

tmp[idx[j]] = '1'

elif (tmp[idx[j]] == '1'):

tmp[idx[j]] = '0'

else:

print("just for extension.")

mk[i] = ''.join(tmp)

mk = self._decode(mk, self._dnaLen)

else:

rows = mk.shape[0]

columns = mk.shape[1]

idx = numpy.where(numpy.random.rand(rows,1) < prop_mut)[0]

mk[idx] = mk[idx] + numpy.random.randn(idx.shape[0], columns)

for i in range(rows):

for j in range(columns):

mk[i][j] = numpy.clip(mk[i][j], self._min[j], self._max[j])

return mk

# 轮盘赌选择法

def _select(self, values, pk):

indexes = []

min = numpy.min(values)

values -= min # 将values的值转换为正值,方便下面的操作

summation = numpy.sum(values)

population = values.shape[0]

data = [(pk[i], values[i]) for i in range(population)]

sorteddata = sorted(data, key = lambda ele: ele[1])

for i in range(population):

test = numpy.random.rand()

sum = 0.0

for j in range(population):

sum += sorteddata[j][1]

if (sum >= test*summation):

indexes.append(j)

break

mk = numpy.zeros(pk.shape)

for i in range(population):

idx = indexes[i]

mk[i] = sorteddata[idx][0]

return mk

# iterations: 最大迭代次数

# population: 种群数量

# prop_cross: 交叉概率

# prop_mut: 变异概率

def run(self, iterations, population, prop_cross, prop_mut):

columns = len(self._min)

p0 = numpy.random.randn(population, columns) # 初始种群,每行为一组输入/一个个体

r = [(self._max[i] - self._min[i])/2.0 for i in range(columns)]

centerPoint = [self._min[i] + r[i] for i in range(columns)]

for i in range(population):

for j in range(columns):

p0[i][j] = centerPoint[j] + p0[i][j]*r[j]

p0[i][j] = numpy.clip(p0[i][j], self._min[j], self._max[j])

values = numpy.zeros(population)

pk = p0

max = 0.0

x_max = 0.0

for iter in range(iterations): # 开始迭代

for i in range(population):

values[i] = self._func(*pk[i])

idx = numpy.argmax(values)

x = pk[idx]

y = values[idx]

if (y > max):

max = y

x_max = x

mk = self._select(values, pk) # 选择mk

pk = self._evolve(mk, prop_cross, prop_mut) # 进化

return (x_max, max)

代码中有注释,比较容易懂。但由于时间问题,部分代码仅实现了功能,没好好优化,导致无论代码格式还是算法本身,都比较丑。

接下来给出用法和测试代码:

test.py

# -*- coding: utf-8 -*-

import GenericAlgorithm as GA

def function(x, y):

term1 = 3*numpy.power(1-x, 2)*numpy.exp(-numpy.power(x,2)-numpy.power(y+1,2))

term2 = -10*(x/5 - numpy.power(x,3) - numpy.power(y,5))*numpy.exp(-numpy.power(x,2)-numpy.power(y,2))

term3 = -numpy.exp(-numpy.power(x+1,2)-numpy.power(y,2))/3

return term1 + term2 + term3

ga = GA.GenericAlgorithm(func=function, min=[-3,-3], max=[3,3], encoding=True, dnaLength=32)

(x, y) = ga.run(50, 20, 0.75, 0.0075)

print("GA: x = ", x, ", y = ", y)

xmax = (-0.0093, 1.5814)

ymax = function(xmax[0], xmax[1])

print("Real: x = ", xmax, ", y = ", ymax)

最终计算结果如下:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值