优化模型算法

优化问题
1、遗传算法
遗传算法采用“优胜劣汰,适者生存”的生物进化原理,按照所选择的适应度函数并通过遗传中的复制、交叉、变异对个体进行筛选,适应度高的被留下来,组成新的群体。

它主要包括三个方面:(1)复制:从一个旧群体中选择适应度高的在下一代中更可能被保留下来。 (2)交叉 :通过两个个体的交换组合,产生新的优良品种。交叉又有单点交叉、两点交叉、一致交叉、顺序交叉和周期交叉,其中单点交叉运用最广。单点交叉:任意选择两个染色体,随机选择一个交换点位置,交换两个染色体右边的部分。 (3)变异:变异运算用来模拟生物在自然的遗传环境中因为各种偶然因素引起的基因突变。算法中以很小的概率随机改变(染色体某一位置)的值,表现为随机将某一基因1变为0,0变为1。

算法流程为:初始化群体---->计算各个个体的适应度---->根据适应度选择个体(适应度高的留下,适应度低的淘汰)----->按照一定的概率进行交叉、变异来产生新的优良品种----->形成新的群体计算适应度(迭代)----->满足终止条件,输出结果

算法特点:(1)直接对结构对象进行操作 (2)具有隐含并行性和更好的全局寻优能力 (3)能自动获取和指导优化的搜索空间,自适应调整方向,不需要确定的规则

2、模拟退火算法

它采用类似于物理退火的过程,先在一个高温状态下,逐渐退火,在每个温度下进行状态转移,最终达到物理基态。

模拟退火算法从某一高温出发,以预设的领域函数,产生新的状态。比较新旧状态下的能量,如果新状态能量小于旧状态,则状态发生变化。否则,以Metropolis接受准则发生变化。当状态稳定后便可以开始降温,在下一温度继续迭代。

Metropolis准则:温度为T,当前状态i,新状态j,若Ei>Ej,则接受j为当前状态;否则,计算状态j与状态i的比值,若大于[0,1)产生的随机数,则接受j为当前状态。它以概率形式接受新状态,避免局部最优。

领域函数:通常在当前状态的领域结构以一定概率方式产生,概率分布可以是均匀分布、正态分布、指数分布等。

该算法的核心主要是内外两次循环,内循环模拟同一温度下多次的状态转移,外循环为进行的迭代次数。

该算法的初始温度和终止温度过低或过高都会延长搜索时间,而降温太快又容易漏掉全局最优,因此要选择合适的冷却进度表。

模拟退火算法它主要是在每一次的迭代下,寻找这次迭代的最优解(局部搜索,当前状态和下一状态进行比较),然后模拟降温过程进行迭代。若是降温的越慢,得到的最优解更精确,但搜索时间过长。由于计算速度和时间限制,在优化效果和计算时间上存在矛盾,优化效果不理想。

遗传算法它可以进行多个个体同时比较,有潜在的并行性。但是他得三个算子的实现有参数(如交叉和变异的概率),参数的选择大多依靠经验,它可能会影响效果。

3、粒子群算法

粒子群算法通过更新每次迭代的局部最优和全局最优来更新粒子的速度和位置,它保留了全局和局部,对于较快收敛和避免过早陷入局部最优都有较好的效果。

粒子群算法和遗传算法都可以同时比较多个个体寻找最优解,不同的是粒子群算法的每个个体还要和过去的个体进行比较,而遗传算法是把适应度大的较大概率的保留到下一代中,适应度小的淘汰。模拟退火算法它是对单个个体温度不变下,状态转移,求目标函数值更新最优解,随着温度不断降低,状态转移的范围也逐渐变小。

//遗传算法
import numpy as np 
DNA_size=10
pops=60
jiaohuan=0.7
bianyi=0.003
gen=100
x_bound=[-3,3]
y_bound=[-3,3]
def fun(x,y):
    return 100.0*(y-x**2.0)**2.0+(1-x)**2.0
def get_fitness(pop):
    x,y=trans(pop)
    pred=fun(x,y)
    return pred
def trans(pop):
    x_pop=pop[:,0:DNA_size]
    y_pop=pop[:,0:DNA_size]
    x=x_pop.dot(2**np.arange(DNA_size)[::-1])/float(2**DNA_size -1)*(x_bound[1]-x_bound[0])+x_bound[0]
    y=y_pop.dot(2**np.arange(DNA_size)[::-1])/float(2**DNA_size-1)*(x_bound[1]-x_bound[0])+x_bound[0]
    return x,y
def crossover(pop):
    new_pop=[]
    pred=get_fitness(pop)
    index=np.argmax(pred)
    index2=np.argmin(pred)
    for father in pop:
        if (father == pop[index2]).all()==True:
            child=pop[index]
        else:
            child=father
        if np.random.rand()<jiaohuan:
            mother=pop[np.random.randint(pops)]
            cross_point=np.random.randint(low=0,high=DNA_size*2)
            child[cross_point:]=mother[cross_point:]
        child=mutation(child)
        new_pop.append(child)
    return new_pop
def mutation(child):
    if np.random.rand()<bianyi :
        mutate_point=np.random.randint(0,DNA_size)
        child[mutate_point]=child[mutate_point]^1
    return child
def select(pop,fitness):
    idx=np.random.choice(np.arange(pops),size=pops,replace=True,p=(fitness)/(fitness.sum()))
    return pop[idx]
def print_info(pop):
    fitness=get_fitness(pop)
    max_index=np.argmax(fitness)
    print("最优解:",fitness[max_index])
    x,y=trans(pop)
    print("最优基因型:",pop[max_index])
    print("最优解的x,y :",x[max_index],y[max_index])
if __name__=="__main__":
    pop=np.random.randint(2,size=(pops,DNA_size*2))
    fitness=get_fitness(pop)
    for i in range(gen):
        pop=np.array(crossover(pop))
        fitness=get_fitness(pop)
        pop=select(pop,fitness)
    print_info(pop)
//模拟退火算法
import numpy as np
import matplotlib.pyplot as plt
import math
def fun(x):
    y=x**3-60*x**2-4*x+6
    return y
T=1000
Tmin=10
x=np.random.uniform(low=0,high=100)
k=50
t=0
y=0
while T>=Tmin:
    for i in range(k):
        y=fun(x)
        xnew=x+np.random.uniform(low=-0.055,high=0.055)*T
        if (0<=xnew and xnew<=100):
            ynew=fun(xnew)
            if ynew-y<0:
                x=xnew
            else:
                p=math.exp(-(ynew-y)/T)
                r=np.random.uniform(low=0,high=1)
                if r<p:
                    x=xnew
    t +=1
    print(t)
    T=1000/(1+t)
print(x,  fun(x))
//粒子群算法
import numpy as np
import matplotlib.pyplot as plt


class PSO(object):
    def __init__(self, population_size, max_steps):
        self.w = 0.6  # 惯性权重
        self.c1 = self.c2 = 2
        self.population_size = population_size  # 粒子群数量
        self.dim = 2  # 搜索空间的维度
        self.max_steps = max_steps  # 迭代次数
        self.x_bound = [-10, 10]  # 解空间范围
        self.x = np.random.uniform(self.x_bound[0], self.x_bound[1],
                                    (self.population_size, self.dim))  # 初始化粒子群位置
        self.v = np.random.rand(self.population_size, self.dim)  # 初始化粒子群速度
        fitness = self.calculate_fitness(self.x)
        self.p = self.x  # 个体的最佳位置
        self.pg = self.x[np.argmin(fitness)]  # 全局最佳位置
        self.individual_best_fitness = fitness  # 个体的最优适应度
        self.global_best_fitness = np.min(fitness)  # 全局最佳适应度

    def calculate_fitness(self, x):
        return np.sum(np.square(x), axis=1)

    def evolve(self):
        fig = plt.figure()
        for step in range(self.max_steps):
            r1 = np.random.rand(self.population_size, self.dim)
            r2 = np.random.rand(self.population_size, self.dim)
            # 更新速度和权重
            self.v = self.w*self.v+self.c1*r1*(self.p-self.x)+self.c2*r2*(self.pg-self.x)
            self.x = self.v + self.x
            plt.clf()
            plt.scatter(self.x[:, 0], self.x[:, 1], s=30, color='k')
            plt.xlim(self.x_bound[0], self.x_bound[1])
            plt.ylim(self.x_bound[0], self.x_bound[1])
            plt.pause(0.1)
            fitness = self.calculate_fitness(self.x)
            # 需要更新的个体
            update_id = np.greater(self.individual_best_fitness, fitness)
            self.p[update_id] = self.x[update_id]
            self.individual_best_fitness[update_id] = fitness[update_id]
            # 新一代出现了更小的fitness,所以更新全局最优fitness和位置
            if np.min(fitness) < self.global_best_fitness:
                self.pg = self.x[np.argmin(fitness)]
                self.global_best_fitness = np.min(fitness)
            print('step: %.d, best fitness: %.5f, mean fitness: %.5f' % (step+1, self.global_best_fitness, np.mean(fitness)))


pso = PSO(100, 100)
pso.evolve()
plt.title("minimum sum square")
plt.show()

你可能感兴趣的:(笔记)